A-A+

MySQL-死锁

2018年12月02日 技术, 默认 暂无评论 阅读 2,110 次

本文基于MySQL的数据库引擎InnoDB,通过本文了解:

1. 死锁。

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。以下是一些示例。

更新时互相等待

  1. #第一个事务
  2. START TRANSACTION;
  3. #第一步,更新1111这条数据
  4. UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '1111';
  5. #第三步,更新2222这条数据
  6. UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '2222';
  7. #第五步,提交事务
  8. COMMIT;
  1. #第二个事务
  2. START TRANSACTION;
  3. #第二步,更新2222这条数据
  4. UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '2222';
  5. #第四步,更新1111这条数据
  6. UPDATE test2 SET sum_count = sum_count + 1 WHERE id = '1111';
  7. #第六步,提交事务
  8. COMMIT;

死锁报错

SELECT ... FOR UPDATE 排它锁

  1. #第一个事务
  2. START TRANSACTION;
  3. #第一步,对1111,2222加锁
  4. SELECT * FROM test2 WHERE id in ('1111', '2222') FOR UPDATE;
  5. #第三步,对3333,4444加锁
  6. SELECT * FROM test2 WHERE id in ('3333', '4444') FOR UPDATE;
  7. #第五步,提交事务
  8. COMMIT;
  1. #第二个事务
  2. START TRANSACTION;
  3. #第二步,对3333,4444加锁
  4. SELECT * FROM test2 WHERE id in ('3333', '4444') FOR UPDATE;
  5. #第四步,对1111,2222加锁
  6. SELECT * FROM test2 WHERE id in ('1111', '2222') FOR UPDATE;
  7. #第六步,提交事务
  8. COMMIT;

死锁报错

依赖索引列删除,同时插入数据

数据表内容:

索引设置:

  1. #第一个事务
  2. START TRANSACTION;
  3. #第一步,删除2222这条数据
  4. DELETE FROM test2 WHERE name = '2222';
  5. #第三步,插入7777这条数据
  6. INSERT INTO test2(id, name, sum_count) VALUES('7777', '7777', 1);
  7. #第五步,提交事务
  8. COMMIT;
  1. #第一个事务
  2. START TRANSACTION;
  3. #第二步,删除5555这条数据
  4. DELETE FROM test2 WHERE name = '5555';
  5. #第四步,插入3333这条数据
  6. INSERT INTO test2(id, name, sum_count) VALUES('3333', '3333', 1);
  7. #第六步,提交事务
  8. COMMIT;

事务报错

原因:当加入非主键索引后,两个事务都拿到了相同区间(当前最大-无穷大)的锁,所以会产生死锁。

最后

合理的设计业务逻辑,合理的设计事务大小,合理的使用索引。

给我留言

Copyright © 字痕随行 保留所有权利.   Theme  Ality

用户登录

分享到: