在为一个客户排除死锁问题时我遇到了一个有趣的包括InnoDB间隙锁的情形。对于一个WHERE子句不匹配任何行的非插入的写操作中,我预期事务应该不会有锁,但我错了。让我们看一下这张表及示例UPDATE。
伊吾网站建设公司创新互联公司,伊吾网站设计制作,有大型网站制作公司丰富经验。已为伊吾上1000+提供企业网站建设服务。企业网站搭建\成都外贸网站制作要多少钱,请找那个售后服务好的伊吾做网站的公司定做!
- mysql> SHOW CREATE TABLE preferences \G
- *************************** 1. row ***************************
- Table: preferences
- Create Table: CREATE TABLE `preferences` (
- `numericId` int(10) unsigned NOT NULL,
- `receiveNotifications` tinyint(1) DEFAULT NULL,
- PRIMARY KEY (`numericId`)
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1
- 1 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 numericId = '2';
- Query OK, 0 rows affected (0.01 sec)
- Rows matched: 0 Changed: 0 Warnings: 0
InnoDB状态显示这个UPDATE在主索引记录上持有了一个X锁:
- ---TRANSACTION 4A18101, ACTIVE 12 sec
- 2 lock struct(s), heap size 376, 1 row lock(s)
- MySQL thread id 3, OS thread handle 0x7ff2200cd700, query id 35 localhost msandbox
- Trx read view will not see trx with id >= 4A18102, sees < 4A18102
- TABLE LOCK table `test`.`preferences` trx id 4A18101 lock mode IX
- RECORD 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: 0
- mysql2> 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: 0
- mysql1> INSERT INTO preferences (numericId, receiveNotifications) VALUES ('1', '1'); -- This one goes into LOCK WAIT
- mysql2> 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事务隔离。
原文链接:http://www.oschina.net/translate/one-more-innodb-gap-lock-to-avoid
网页名称:一个需要避免的InnoDB间隙锁
文章URL:http://www.mswzjz.cn/qtweb/news6/19456.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能