MYSQL数据库MySQL中InnoDB的间隙锁问题

《MYSQL数据库MySQL中InnoDB的间隙锁问题》要点:
本文介绍了MYSQL数据库MySQL中InnoDB的间隙锁问题,希望对您有用。如果有疑问,可以联系我们。

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

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是另一个,查询的顺序如下:
 
MYSQL实例

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事务隔离.
MYSQL实例

相关文章

在正式开始之前,我们先来看下 MySQL 服务器的配置和版本号信...
&gt; [合辑地址:MySQL全面瓦解](https://www.cnblogs.c...
物理服务机的CPU、内存、存储设备、连接数等资源有限,某个时...
1 回顾 上一节我们详细讲解了如何对数据库进行分区操作,包括...
navicat查看某个表的所有字段的详细信息 navicat设计表只能一...
文章浏览阅读4.3k次。转载请把头部出处链接和尾部二维码一起...