MySQL中InnoDB的间隙锁问题

 更新时间:2015年07月03日 11:56:47   投稿:goldensun  
这篇文章主要介绍了MySQL中InnoDB的间隙锁问题,提醒用户注意死锁情况,需要的朋友可以参考下

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

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事务隔离。

相关文章

  • Windows安装MySQL8.0.28.0.msi方式(图文详解)

    Windows安装MySQL8.0.28.0.msi方式(图文详解)

    这篇文章主要介绍了Windows安装MySQL8.0.28.0.msi,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • mysql 8.0.15 压缩版安装图文教程

    mysql 8.0.15 压缩版安装图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.15 压缩版安装图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • 解决远程连接mysql很慢的方法(mysql_connect 打开连接慢)

    解决远程连接mysql很慢的方法(mysql_connect 打开连接慢)

    有次同事提出开发使用的mysql数据库连接很慢,因为我们的mysql开发数据库是单独一台机器部署的,所以认为可能是网络连接问题导致的。
    2011-07-07
  • MySQL使用命令创建、删除、查询索引的介绍

    MySQL使用命令创建、删除、查询索引的介绍

    今天小编就为大家分享一篇关于MySQL使用命令创建、删除、查询索引的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • 设计性能更优MySQL数据库schema

    设计性能更优MySQL数据库schema

    这篇文章主要介绍了设计性能更优MySQL数据库schema,文章通过数据类型优化展开对主题内容的详细介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Mysql导入导出时遇到的问题解决

    Mysql导入导出时遇到的问题解决

    这篇文章主要给大家介绍了关于Mysql导入导出时遇到问题的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Mysql具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • 详解MySQL的用户密码过期功能

    详解MySQL的用户密码过期功能

    这篇文章主要为大家详细介绍了MySQL的用户密码过期功能的相关资料,需要的朋友可以参考下
    2016-02-02
  • 你知道mysql中空值和null值的区别吗

    你知道mysql中空值和null值的区别吗

    这篇文章主要给大家介绍了关于mysql中空值和null值区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • MySQL实现批量检查表并进行repair与optimize的方法

    MySQL实现批量检查表并进行repair与optimize的方法

    这篇文章主要介绍了MySQL实现批量检查表并进行repair与optimize的方法,结合实例形式分析了MySQL批量修复与优化表的相关技巧,需要的朋友可以参考下
    2016-04-04
  • Mysql查询或导出结果添加序号字段实现方法

    Mysql查询或导出结果添加序号字段实现方法

    这篇文章主要介绍了Mysql查询或导出结果添加序号字段实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04

最新评论