一:RC 隔离级别下通过next key lock 来保证唯一约束生效
我们知道在RC隔离级别中几乎不会出现 Gap Lock,但是官方文档中列出了如下两个例外情况(在外键约束和唯一性约束时还是会使用Gap Lock,即使在RC隔离级别下)。
二:未使用 next key lock,RC隔离级别下出现唯一约束失效BUG
我实话按我个人的理解,RC隔离级别下确实不需要使用Gap Lock 来保证唯一性约束。有人跟我有同样的想法,并且MySQL 做了修改去掉了使用Gap Lock 来保证唯一性,但是很不幸的是,修改后发生了唯一约束失效的BUG,bug地址如下:
bug#68021
上面的bug中以及下面的阿里云内核月报文章中,都给出了触发bug的测试脚本
MySQL · 内核分析 · InnoDB主键约束和唯一约束的实现分析
在内核月报中给出的触发bug的例子如下:
Transaction 1:
begin;
delete from t1 where c2 = 5; // 加X NOT_GAP lock,成功
Transaction 2:
insert into t1 select 1,5; // 加S NOT_GAP lock,等待
Transaction 3:
insert into t1 select 2,5; // 加S NOT_GAP lock,等待
Transaction 1:
commit;
T1 释放X NOT_GAP lock
T2 加S NOT_GAP lock成功
T3 加S NOT_GAP lock成功(S锁互相兼容)
T2 加X insert intention lock成功(X IK和S RK兼容)
T3 加X insert intention lock成功(X IK和S RK,X IK均兼容)
T2 插入记录成功
T3 插入记录成功
三:我的疑惑
上面例子中看似解释是很合理的,但是我有一个疑惑,在 T1 提交后,T2,T3 确实会成功的加上 S NOT_GAP lock。但是有一个重要的环节好像被忽略了,那就是修改或者读取页面需要对页面加上RW-X-LATCH 或者RW-S-LATCH锁,所以正确的过程应该如下
1) T2 申请页面上的 RW-X-LATCH 锁,成功后进行唯一约束检查发现冲突,所以
T2 释放 RW-X-LATCH 并等待S NOT_GAP lock
2) T3 申请页面上的 RW-X-LATCH 锁,成功后进行唯一约束检查发现冲突,所以
T3 释放 RW-X-LATCH 并等待S NOT_GAP lock
3) T1事务提交
4) T1事务提交后,T2,T3获取了各自等待的 S NOT_GAP lock,但是他们获取的锁都是在没有 RW-X-LATCH 锁的保护下获得的,所以这时T2和T3 应该重新获取 RW-X-LATCH锁,在该锁的保护下重新判断加锁,因为这个过程是串行的,所以我认为不应该导致两条记录都被插入成功,最后只应该有一条插入成功
NOTE:第三部分只是个人的疑惑,能力有限,如果哪位大神对这一块比较清楚的,望请不吝赐教
问题概述最近我们遇到一个
MySQL
的问题,分析后很有代表意义,特地写出来供大家参考。出现问题是,数据库先是被置为只读,然后过了一段时间,
MySQL
直接Crash掉了发生Crash时
MySQL
的error日志中打印了以下内容:----------SEMAPHORES----------OS WAIT ARRAY INFO: reservation count 1246555--Thread 1403...
在上一篇文章中,我提到
MySQL
对自增主键锁做了优化,尽量在申请到自增 id 以后,就释放自增锁。
因此,insert 语句是一个很轻量的操作。不过,这个结论对于“普通的 insert 语句”才有效。也就是说,还有些 insert 语句是属于“特殊情况”的,在执行过程中
需要
给其他资源加锁,或者无法在申请到自增 id 以后就立马释放自增锁。
那么,今天这篇文章,我们就一起来聊聊这个话题。
insert … select 语句
我们先从昨天的问题说起吧。表 t 和 t2 的表结构、初始化数据语句
为什么
MySQL
的默认隔级别是rr,这是历史原因,在
MySQL
5.1之前,binlog日志只有statment的格式,在主从复制的时候,由于事务commit的先后不一样,生成的binlog日志在从节点执行可以回造成主从不一致,所以
MySQL
默认
隔离级别
用rr,rr有间隙锁和临键锁,能
保证
主从复制的一致性。2,死锁的几率更小。3,
rc
还支持半一致性读,当update进行修改数据的时候,对于不满足更新条件的记录,可以提前释放锁,提升并发度。两者的区别:rr的
隔离级别
更高,相对安全一点,
rc
的性能更高,并发快。
background threadsemphoreslatest detected dead
lock
(该部分内容不一定输出,只有在系统出现过死锁情况下才输出)latest foreign
key
error(该部分内容不一定输出,只有在系统出现过外键错误情况下才输出)t
rw
-
lock
The low-level object thatInnoDBuses to represent and enfo
rc
e shared-access
lock
sto internal in-memory data structures following certain rules. Contrast withmutexes, whichInnoDBuses to represent a...
背景:.这是一个臭名昭彰的问题,Innodb的btree发生合并/分裂等可能修改B-tree的操作时,都
需要
对其加排他的索引锁,这时候是无法对该索引进行读写操作的,极大的影响了性能;关于index
lock
,可以看看大神Domas的这篇博文:“Innodb
lock
ing makes me sad” 以及Vadim的这篇博客.总而言之,
MySQL
5.7.2的这个功能点的改进是万众期待的!.以下是...
在之前的博客中,我写了一系列的文章,比较系统的学习了
MySQL
的事务、
隔离级别
、加锁流程以及死锁,我自认为对常见 SQL 语句的加锁原理已经掌握的足够了,但看到热心网友在评论中提出的一...
作者:网易数据库团队DDB(网易杭研自研的
MySQL
数据库中间件产品)团队小伙伴发现了一个问题,觉得比较奇怪。于是找到我们,希望解释下。过程中除解释了问题的现象,也通过代码了解了更多的InnoDB DML执行逻辑,还发现了
MySQL
/InnoDB官方在二级
唯一索引
冲突
检查
时加锁行为的反复。本系列打算用三四篇文章来聊聊这个事情。这是第一篇,说清问题并提供解释。问题描述表dt包含了一个主键,一个复合唯...
文章的产生是因为生产上遇到一个死锁案例,根据此案例分析引申出比较多的内容,故总结一下。死锁分析数据库版本:
MySQL
5.6.39社区版事务
隔离级别
:
RC
死锁日志这个死锁日志中,可以得到上锁信息如下:事务28608410 , 申请X类型记录锁时,发生了锁等待,对应的记录就是user_id=195578这条(16进制的2fbfa就是195578)事务28608409持有user_id=19557...
gap
lock
Gap
lock
ing is not needed for statements that
lock
rows using a unique index to sea
rc
h for a unique row. (This does not include the case that the sea
rc
h condition includes only some columns of...
InnoDB的锁机制:数据库使用所是为了支持更好的并发,提供数据的完整性和一致性。InnoDB是一个支持锁的存储引擎,锁的类型有:共享锁(S)、排它锁(X)、意向共享锁(IS)、意向排它锁(IX)。为了支持更好的并发,InnoDB提供了非锁定读:不
需要
等待访问行上的锁释放,读取行的一个快照。该方法是通过InnoDB的一个特写:MVCC实现的。InnoDB的锁分类:Record
Lock
:行锁:单个...
innodb是一个多线程并发的存储引擎,内部的读写都是用多线程来实现的,所以innodb内部实现了一个比較高效的并发同步机制。innodb并没有直接使用系统提供的锁(
latch
)同步结构,而是对其进行自己的封装和实现优化。可是也兼容系统的锁。我们先看一段innodb内部的凝视(
MySQL
-3.23):Semaphore operations in operating systems are slo...
加锁流程一直很迷,尤其几个session搅在一起。自以为的初窥门径其实根本不值一提。今天碰巧搜到有大佬从源码层面分析insert加锁,就顺便记一下。原文博客:https://www.aneasystone.com/a
rc
hives/2018/06/insert-
lock
s-via-
mysql
-sou
rc
e-code.html附前提知识讲接链接:锁的种类-
Mysql
官方文档常见 SQL 语句的加锁分...
最近我们遇到一个
MySQL
的问题,分析后很有代表意义,特地写出来供大家参考。
出现问题是,数据库先是被置为只读,然后过了一段时间,
MySQL
直接Crash掉了
发生Crash时
MySQL
的error日志中打印了以下内容:
SEMAPHORES...
加锁流程一直很迷,尤其几个session搅在一起。自以为的初窥门径其实根本不值一提。今天碰巧搜到有大佬从源码层面分析insert加锁,就顺便记一下。
原文博客:https://www.aneasystone.com/a
rc
hives/2018/06/insert-
lock
s-via-
mysql
-sou
rc
e-code.html
附前提知识讲接链接:
锁的种类-
Mysql
官方文档
CREATE TABLE `person` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` va
rc
har(100) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`test` bigint(20) DEFAULT NULL,
`tests` bigint(20) DEFAULT NULL...
1、行锁:
我们知道myisam默认是表锁,锁的粒度较大,因此适用读多写少的场景。在innodb中默认是行锁,每次增删改一行数据,会将该行锁住。后续的线程操作改行数据会被阻塞,直到持有行锁的线程释放锁。
2、间隙锁:
间隙锁的出现是为了在innodb的可重复读
隔离级别
下,解决幻读问题产生的。间隙锁会封锁该条记录相邻两个键之间的空白区域,防止其它事务在这个区域内插入、修改、删除数据;所谓间隙是将数据...