• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

MySQL中InnoDB的间隙锁问题_MySQL

mysql 搞代码 4年前 (2022-01-09) 57次浏览 已收录 0个评论

在为一个客户排除死锁问题时我遇到了一个有趣的包括InnoDB间隙锁的情形。对于一个WHERE子句不匹配任何行的非插入的写操作中,我预期事务应该不会有锁,但我错了。让我们看一下这张表及示例UPDATE。

mysql> SHOW CREATE TABLE preferences \G*************************** 1. row ***************************    Table: preferencesCreate Table: CREATE TABLE `preferences` ( `numericId` int(10) unsigned NOT NULL, `receiveNotifications` tinyint(1) DEFAULT NULL, PRIMARY KEY (`numericId`)) ENGINE=InnoDB DEFAULT CHARSET=latin11 row in set (0.00 sec)mysql> BEGIN;Query OK, 0 rows affected (0.00 sec)mysql> SELECT COUNT(*) FROM preferences;+----------+| COUNT(*) |+----------+|    0 |+----------+1 row in set (0.01 sec)mysql> UPDATE preferences SET receiveNotifications='1' WHERE numeri<i style="color:transparent">本文来源gaodai$ma#com搞$$代**码)网8</i>cId = '2';Query OK, 0 rows affected (0.01 sec)Rows matched: 0 Changed: 0 Warnings: 0

InnoDB状态显示这个UPDATE在主索引记录上持有了一个X锁:

---TRANSACTION 4A18101, ACTIVE 12 sec2 lock struct(s), heap size 376, 1 row lock(s)MySQL thread id 3, OS thread handle 0x7ff2200cd700, query id 35 localhost msandboxTrx read view will not see trx with id >= 4A18102, sees < 4A18102TABLE LOCK table `test`.`preferences` trx id 4A18101 lock mode IXRECORD LOCKS space id 31766 page no 3 n bits 72 index `PRIMARY` of table `test`.`preferences` trx id 4A18101 lock_mode X

这是为什么呢,Heikki在其bug报告中做了解释,这很有意义,我知道修复起来很困难,但略带厌恶地我又希望它能被差异化处理。为完成这篇文章,让我证明下上面说到的死锁情况,下面中mysql1是第一个会话,mysql2是另一个,查询的顺序如下:

mysql1> BEGIN;Query OK, 0 rows affected (0.00 sec)mysql1> UPDATE preferences SET receiveNotifications='1' WHERE numericId = '1';Query OK, 0 rows affected (0.00 sec)Rows matched: 0 Changed: 0 Warnings: 0mysql2> BEGIN;Query OK, 0 rows affected (0.00 sec)mysql2> UPDATE preferences SET receiveNotifications='1' WHERE numericId = '2';Query OK, 0 rows affected (0.00 sec)Rows matched: 0 Changed: 0 Warnings: 0mysql1> INSERT INTO preferences (numericId, receiveNotifications) VALUES ('1', '1'); -- This one goes into LOCK WAITmysql2> INSERT INTO preferences (numericId, receiveNotifications) VALUES ('2', '1');ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

现在你看到导致死锁是多么的容易,因此一定要避免这种情况——如果来自于事务的INSERT部分导致非插入的写操作可能不匹配任何行的话,不要这样做,使用REPLACE INTO或使用READ-COMMITTED事务隔离。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:MySQL中InnoDB的间隙锁问题_MySQL
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址