多线程以不同顺序对相同资源加锁导致死锁。
时间
会话A
会话B
1BEGIN; 2SELECT * FROM t WHERE a = 1 FOR UPDATE;BEGIN;3 SELECT * FROM t WHERE a = 2 FOR UPDATE;4SELECT * FROM t WHERE a = 2 FOR UPDATE;
-- 开始等待B释放锁
5SELECT * FROM t WHERE a = 1 FOR UPDATE;
-- 等待A释放锁,产生死锁
解决方案:
1.可以在业务层面上保证加锁的顺序一致;
2.大事务拆分成小事务。
S锁X锁的陷阱。
时间
会话A
会话B
1BEGIN; 2INSERT INTO test_copy SELECT * FROM test WHERE id =8;
-- 对test表中id = 8的记录加S锁,等同于
SELECT * FROM test WHERE id = 8 LOCK IN SHARE MODE;
BEGIN;3SELECT * FROM test WHERE id = 8 FOR UPDATE;
-- 申请对id = 8的记录加X锁,开始等待
4SELECT * FROM test WHERE id = 8 FOR UPDATE;
-- 申请对资源加X锁,发现已经被B锁定,等待B释放X锁,产生死锁
解决方案:
将会话A中加的S锁改成X锁:INSERT INTO test_copy SELECT * FROM test WHERE id =8 FOR UPDATE;
保证会话A结束前,会话B不会对资源加X锁。