参考:http://blog.csdn.net/mageshuai/article/details/4544188
1.丢失更新
时间 | 事务1 | 事务2 |
T1 | 开始事务 | |
T2 | 开启事务 | |
T3 | 读取初始数据4 | |
T4 | 读取初始数据4 | |
T5 | 4+10,并且更新到数据库 | |
T6 | 提交事务 | |
T7 | 4-4,并且更新到事务 | |
T8 | 报错 | |
T9 | 回滚事务 |
这里T9回滚事务在一般情况下应该回滚到4,但是sqlserver未提交隔离级别(最低隔离)是回滚到事务2提交的结果:14,所以最终结果是14,也就是目前sqlserver不存在丢失更新的问题。
测试代码(最终结果:14):
--事务1 set transaction isolation level READ UNCOMMITTED begin try begin tran declare @deptidTmp int WAITFOR DELAY '00:00:3' set @deptidTmp=(select deptid from Student where stuid=1) WAITFOR DELAY '00:00:5' update Student set deptid=@deptidTmp-4 where stuid=1 insert into department(depid,depname) values (1,'') --报错的语句 commit tran end try begin catch rollback tran end catch --事务2 set transaction isolation level READ UNCOMMITTED begin try begin tran declare @deptidTmp int WAITFOR DELAY '00:00:4' set @deptidTmp=(select deptid from Student where stuid=1) --读到4 update Student set deptid=@deptidTmp+10 where stuid=1 --全部干掉,结果为0 commit tran end try begin catch rollback tran end catch
理论分析:事务1读完之后,对目标行没有加任何锁,事务2在读取和更新完成后,目标行数据变为14,事务1回滚到14而不是他一开始读的4,这可能是SQL SERVER的事务机制决定的。
事务1读完之后,要想对目标行加上S锁,需要提升到可重复读隔离级别,这样事务2在更新的时候会被阻塞(等待),直到事务1回滚,才会把最终结果更新为14.
2.脏读