MySQL中InnoDB的间隙锁问题
作者:goldensun 发布时间:2024-01-25 11:13:58
标签: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事务隔离。


猜你喜欢
- 在本文中,我将说明如何用SQL Server的工具来优化数据库索引的使用,本文还涉及到有关索引的一般性知识。 关于索引的常识 影响到数据
- 本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11
- 原理采用Python requests发起请求监测的URL,检测Http响应状态及是否超时,如果Http状态异常或响应超时,则通过聚合云推的
- 目录一.定义二.命名方法2.1小驼峰命名法2.2大驼峰命名法2.3下划线命名法三.命名规则3.1标识符3.2关键字四.使用方法4.1单变量赋
- Oracle的执行计划一句话命令:set autotrace on
- 404页面对于站长来说应该并不陌生,其作用无碍乎二点:提高用户体验和增强对搜索引擎的友好性。去年在跟几个朋友在聊天的时候,跟我说404页面不
- 阅读本文需要有其他语言的编程经验。在 JavaScript 中数组是对象(而非线性分配的内存)。通过数组 literal 来创建数组:var
- python的列表list可以用for循环进行遍历,实际开发中发现一个问题,就是遍历的时候删除会出错,例如l = [1,2,3,4]for
- 场景描述在update表的时候出现DeadlockLoserDataAccessException异常 (Deadlock found wh
- Python pip安装lxml出错的问题解决办法1. 在使用pip安装lxml过程中出现了一下错误: &
- 环境准备:全局安装jade: npm install jade -g初始化项目package.json: npm init --yes安装完
- 超级简单实现iframe框架滚动控制,前提要会简单修改原代码。step1:插入iframe标签在你想要的位置。<iframe 
- Python中滑动平均算法(Moving Average)方案:#!/usr/bin/env python# -*- coding: utf
- 先以一个大牛的一段关于Python Metapgramming的著名的话来做开头:Metaclasses are deeper magic
- 当我们在安装scrapy的过程中出现了Twisted错误,当我们有继续安装Twisted的时候,又继续报错,通过一系列的查询和了解,终于发现
- 具体代码和实现方法见下:第一个办法,这个程序可以进行万亿以下的货币金额转换(够用的了吧),其中汉字与数字均按一位计:Function&nbs
- 在网上找了找也没找到合适的最后自己测试用 存入:Replace("\r\n", "<br/>&qu
- 在本节中,您将开始修改为电影控制器所新加的操作方法和视图。然后,您将添加一个自定义的搜索页。在浏览器地址栏里追加/Movies, 浏览到Mo
- 根据微软论坛作者的英文解释,.NET framework 4.0 安装失败回滚貌似是因为“msvcr100_clr0400.d
- <%'asp事务处理。'测试数据库为sql server,服务器为本机,数据库名为test,表名为a,两个字段id(i