A-A+
MySQL-死锁
本文基于MySQL的数据库引擎InnoDB,通过本文了解:
1. 死锁。
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。以下是一些示例。
更新时互相等待
- #第一个事务
- START TRANSACTION;
- #第一步,更新1111这条数据
- UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '1111';
- #第三步,更新2222这条数据
- UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '2222';
- #第五步,提交事务
- COMMIT;
- #第二个事务
- START TRANSACTION;
- #第二步,更新2222这条数据
- UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '2222';
- #第四步,更新1111这条数据
- UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '1111';
- #第六步,提交事务
- COMMIT;
死锁报错
SELECT ... FOR UPDATE 排它锁
- #第一个事务
- START TRANSACTION;
- #第一步,对1111,2222加锁
- SELECT * FROM test2 WHERE id in ('1111', '2222') FOR UPDATE;
- #第三步,对3333,4444加锁
- SELECT * FROM test2 WHERE id in ('3333', '4444') FOR UPDATE;
- #第五步,提交事务
- COMMIT;
- #第二个事务
- START TRANSACTION;
- #第二步,对3333,4444加锁
- SELECT * FROM test2 WHERE id in ('3333', '4444') FOR UPDATE;
- #第四步,对1111,2222加锁
- SELECT * FROM test2 WHERE id in ('1111', '2222') FOR UPDATE;
- #第六步,提交事务
- COMMIT;
死锁报错
依赖索引列删除,同时插入数据
- #第一个事务
- START TRANSACTION;
- #第一步,删除2222这条数据
- DELETE FROM test2 WHERE name = '2222';
- #第三步,插入7777这条数据
- INSERT INTO test2(id, name, sum_count) VALUES('7777', '7777', 1);
- #第五步,提交事务
- COMMIT;
- #第一个事务
- START TRANSACTION;
- #第二步,删除5555这条数据
- DELETE FROM test2 WHERE name = '5555';
- #第四步,插入3333这条数据
- INSERT INTO test2(id, name, sum_count) VALUES('3333', '3333', 1);
- #第六步,提交事务
- COMMIT;
事务报错
原因:当加入非主键索引后,两个事务都拿到了相同区间(当前最大-无穷大)的锁,所以会产生死锁。
最后
合理的设计业务逻辑,合理的设计事务大小,合理的使用索引。