MySQL死锁记录

编程

今天线上环境偶现了一个 Deadlock found when trying to get lock; try restarting transaction 的报错,排查了一下,下面先模拟一下操作再说下排查流程

  1. 模拟操作

  • 数据库脚本准备

CREATE TABLE t (i INT) ENGINE = INNODB;

INSERT INTO t (i) VALUES(1);

  • A 客户端执行:

START TRANSACTION;

SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;

  • B 客户端执行:

START TRANSACTION;

DELETE FROM t WHERE i = 1;

  • 然后A客户端再执行:

UPDATE t SET i = 2

WHERE i = 1;

这时B客户端就会报死锁的错误

  1. 排查流程

  • 命令行登录MySql服务端

mysql -h 127.0.0.1 -P 3306 -u root -p

  • 查看死锁日志

 show engine innodb status G;

  • 找到日志里的 LATEST DETECTED DEADLOCK 下面的内容

  • 从日志里我们能看到 A 客户端(截图里的 *** (2) TRANSACTION: ) 首先获得了一个 S锁(共享锁),然后 B 客户端要获取 X锁(互斥锁,对应上面的 delete 操作),然后 A 客户端也想要获取 X锁(对应上面的 update 操作),造成了相互等待,形成了死锁。最后的结果是 A 客户端操作执行成功,B 客户端回滚了。

  1. 解决方法

    我在线上遇到的问题是因为表字段没加索引,其中一条SQL造成了全表加锁,在加了索引之后还在观察中。

    官方的说法也是要让事务尽量更新行数小、执行快,减小锁的时间。

以上是 MySQL死锁记录 的全部内容, 来源链接: utcz.com/z/512228.html

回到顶部