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