在上篇文章我们提到,当运行多个事务的时候,并且这些事务方式数据库中的相同数据会出现一系列的并发问题,这些问题汇总起来总共有以下几类.
丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。
脏读:一个事务读到另一个事务为提交的更新数据。
不可重复读:一个事务读到另一个事务已提交的更新数据。
幻像读:一个事务读到另一个事务已提交的新插入的数据。
丢失更新
当多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。
举一个小例子来帮助进一步理解:当事务A和事务B同时修改数据库表的某行的值,
1.事务A将数值改为10000并提交
2.事务B将数值改为20000并提交。这时数据的值为20000,事务A所做的更新将会丢失。
解决办法:对行加锁,只允许并发一个更新事务。
脏读
当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。
1.甲的原工资为10000, 乙将甲的工资改为了15000,此时但未提交事务.
2.甲读取自己的工资 ,发现自己的工资变为了15000!
3.而乙发现操作有误,回滚了事务,甲的工资又变为了10000 像这样,甲记取的工资数15000是一个脏数据。
解决办法:如果在第一个事务提交前,任何其他事务不可读取其修改过的值,则可以避免该问题。
非重复读
当第二个事务多次访问同一行而且每次读取不同的数据时,会发生不一致的分析问题。不一致的分析与未确认的相关性类似,因为其它事务也是正在更改第二个事务正在读取的数据。然而,在不一致的分析中,第二个事务读取的数据是由已进行了更改的事务提交的。而且,不一致的分析涉及多次(两次或更多)读取同一行,而且每次信息都由其它事务更改;因而该行被非重复读取。
在一个事务中前后两次读取的结果并不致,导致了不可重复读。
1.在事务1中,甲读取了自己的工资为10000,操作并没有完成
2.在事务2中,这时乙修改了甲的工资为50000,并提交了事务.
3.在事务1中,甲再次读取自己的工资时,工资变为了50000
解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。
幻像读
当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。
目前工资为10000的员工有5人。
1.事务1,读取所有工资为10000的员工。
2.这时事务2向表插入了一条员工记录,工资也为10000
3.事务1再次读取所有工资为10000的员工共读取到了6条记录,
解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题。
上面所产生的并发问题我们都基本上给出了解决的方案或者建议,也就是用锁.锁机制能有效地解决并发事务时的各种问题,但是也会影响到并发的性能。数据库系统提供了相应的解决方案,我们将在下一篇文章中来了解隔离级别.