前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个InnoDB死锁案例

一个InnoDB死锁案例

原创
作者头像
jackieluo
发布2019-07-25 14:17:21
8680
发布2019-07-25 14:17:21
举报
文章被收录于专栏:Jackie技术随笔Jackie技术随笔

用来做注册失败设备离线重试的服务,上线之后偶尔会打出这样的ERROR日志:

代码语言:txt
复制
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

14.7.5.1 一个 InnoDB 死锁示例

首先, 客户端 A 创建一张表并且插入一条数据,然后开始一个事务。在这个事务中, 通过在共享模式下进行SELECT操作,A 在此行持有一个 S 锁:

代码语言:txt
复制
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也开始一个事务,并试图删除刚刚说的那一行:

代码语言:txt
复制
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也试图删除这一行:

代码语言:txt
复制
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在其中一个客户端抛出错误,并释放它持有的锁。

代码语言:txt
复制
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

这样另一个客户端就可以得到锁,成功删除这一行。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 14.7.5.1 一个 InnoDB 死锁示例
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档