先上代码connectA:
BEGIN TRAN UPDATE dbo.Student SET Sorce=89 WHERE id=5 waitfor delay '00:00:05' SELECT * FROM dbo.Teacher WHERE id=1 COMMIT TRAN
connectB:
BEGIN TRAN UPDATE dbo.Teacher SET Age=21 WHERE Id=1 SELECT * FROM dbo.Student WHERE Id=5 COMMIT TRAN
A的操作:开启事物=》更新表student=》等待5s=》查询表teacher=》提交事物
B的操作:开启事物=》更新表teacher=》查询表student=》提交事物
结果B的操作出现:
Msg 1205, Level 13, State 51, Line 4
Transaction (Process ID 59) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
意思为:出现死锁,B的连接事务回滚
分析:
现在事务的隔离级别为默认的 READ COMMITTED,该级别排他锁和共享锁是不能同时的。
1.当A连接先执行的时候,更新student表,student表会加一个排他锁,等待5秒。
2.此时执行B的操作,更新teacher表,teacher表会加一个排他锁。然后执行查询表student,查询是添加一个共享锁,但student表已经添加了排他锁,只有等待排他锁的释放。
3.A操作的5s等待完成,执行查询teacher表,teacher表在B连接已经加了排他锁,只能等待teacher表排他锁的释放。
4.这个时候就造成了死锁。
5.系统发现死锁后,会根据配置和系统开销估算。哪个事物回滚,哪个提交。
解决方案:
1.降低事物的隔离等级,一般不用。
2.将与业务逻辑无关的查询放到事物外。
3.在事物中表的操作顺序调整为一致。例如B连接改为:
BEGIN TRAN
SELECT * FROM dbo.Student WHERE Id=5
UPDATE dbo.Teacher SET Age=22 WHERE Id=1
COMMIT TRAN