相关文章推荐

一: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的可重复读 隔离级别 下,解决幻读问题产生的。间隙锁会封锁该条记录相邻两个键之间的空白区域,防止其它事务在这个区域内插入、修改、删除数据;所谓间隙是将数据...
 
推荐文章