用来做注册失败设备离线重试的服务,上线之后偶尔会打出这样的ERROR
日志:
2019-07-24 16:05:56|DevRegisterRetryHandler.go:144|ERROR|Error 1213: Deadlock found when trying to get lock; try restarting transaction
更新数据库的操作最后是成功的,分析可能是因为这个服务两个节点都在做重试,对同一行记录并发进行读取及更新时出现冲突导致,查了一下资料:
MySQL 5.7 Reference Manual / ... / An InnoDB Deadlock Example
首先, 客户端 A 创建一张表并且插入一条数据,然后开始一个事务。在这个事务中, 通过在共享模式下进行SELECT
操作,A 在此行持有一个 S
锁:
mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)
mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i |
+------+
| 1 |
+------+
接下来, 客户端B也开始一个事务,并试图删除刚刚说的那一行:
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM t WHERE i = 1;
这个DELETE
操作需要一个 X
锁。由于和客户端A持有的 S
锁冲突,客户端B无法立刻得到这个锁,于是客户端B阻塞,等待这个锁。
最后,客户端A也试图删除这一行:
mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
由于客户端A需要一个X
锁来删除这行,死锁就发生了。这个锁请求没法成功,因为此时客户端B还在等客户端A释放锁S
以拿到锁X
。客户端A也没法将S
锁升级成X
锁,因为客户端B对X
锁的请求排在更前面。结果就是InnoDB
在其中一个客户端抛出错误,并释放它持有的锁。
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
这样另一个客户端就可以得到锁,成功删除这一行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。