首页
学习
活动
专区
圈层
工具
发布

MySQL加锁范围分析

场景: 最近,遇到了一个关于mysql 加锁的问题,将当时的情形简化如下,有一个index_test表,表结构如下所示: mysql> CREATE TABLE `index_test` ( `priv_id...index_id=5的数据也插不进去了,即使是client1加了next-key锁,根据InnoDB关于next-key locks这一节所述,这里next-key locks的范围也应该是(5,6]才对,...然后在网上搜索相关的资料,看看别人有没有遇到过这样的问题,在一篇关于MySQL加锁处理分析的blog中得到了启示,按照blog中组合七:id非唯一索引+RR的理论,gap锁的范围不仅跟被锁定的键有关,还跟主键有关...因此,在我们使用mysql加锁过程中,也首先需要搞清楚,我们的隔离级别是什么,是否开启了binlog等等,然后才能正确分析加锁的范围。...p=771 大神描述Mysql 加锁分析的blog http://hedengcheng.com/?

6.9K72
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    MySQL加锁实战分析

    ENGINE=InnoDB; insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,20,20),(25,25,25); MySQL...加锁的基本单位是next-key lock(前开后闭区间) 查找过程中访问到的对象才会加锁 索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁 索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候...lock,因此加锁范围是(0, 5] 索引c是普通索引,根据规则4,最终会退化成间隙锁(5, 10) 根据规则2,只有访问到的对象才会加锁,由于Session A的查询使用覆盖索引,并不需要访问主键索引...注意我们这里加的是读锁,如果你使用的是for update,MySQL会认为你要更新数据,因此会给主键索引上满足条件的行加上行锁。...c,因此是普通索引,根据规则1,因此在索引c上加了(5, 10]的next-key lock,由于不满足规则3,所以不会退化为行锁,同时由于c不是唯一索引,因此不会退化成行锁 继续向右遍历,由于不满足条件

    1.6K30

    MySQL 加锁处理分析

    先对一条满足条件的记录加锁,返回给MySQL Server,做一些DML操作;然后在读取下一条加锁,直至读取完毕。...关于聚簇索引表的组织方式,可以参考MySQL的官方文档:Clustered and Secondary Indexes 。本文假设读者对这个,已经有了一定的认识,就不再做具体的介绍。...我能想象到的一个答案是: SQL1:不加锁。因为MySQL是使用多版本并发控制的,读不加锁。 SQL2:对id = 10的记录加写锁 (走主键索引)。 这个答案对吗?说不上来。...为什么不是只在满足条件的记录上加锁呢?这是由于MySQL的实现决定的。如果一个条件无法通过索引快速过滤,那么存储引擎层面就会将所有记录加锁后返回,然后由MySQL Server层进行过滤。...深入理解MySQL如何加锁,有两个比较重要的作用: 可以根据MySQL的加锁规则,写出不会发生死锁的SQL; 可以根据MySQL的加锁规则,定位出线上产生死锁的原因; 下面,来看看两个死锁的例子 (一个是两个

    4.3K61

    MySQL InnoDB 加锁机制

    且由于MySQL会对锁的粒度做一定优化, 所以应以实际加锁为准. 1....此时对该表进行更新/插入/删除/加锁都会被阻塞 由于age上并没有索引, 所以select * 和 select age 就没有区别 不使用索引的等值查询, 值不存在 start transaction.../共享锁, 没有对主键索引记录加锁. b) 记录不存在 start transaction; SELECT * FROM user WHERE uni = 55 FOR UPDATE; 对uni=60前的间隙..., 从符合条件的52开始加N-K锁, 加锁到60结束, 同时对id=880的主键索引记录加锁 b) 左闭右开, 左范围存在记录 start transaction; select * from user...uni是唯一索引, 那么52之后必定是比52大的索引记录, 即扫描可以到此为止, 不需要再对60加锁. 有人认为这是InnoDB的一个BUG, 后面介绍主键索引范围查询加锁情况的时候再提.

    3.8K00

    mysql语句加锁分析

    其实并不能完全解决幻读问题, 这里可以参考另一篇博客[mysql事务隔离级别与加锁分析] SERIALIZABLE隔离级别下,需要分为两种情况讨论: 在系统变量autocommit=0时,也就是禁用自动提交时...LOCK IN SHARE MODE 遍历对应二级索引, 找到第一条满足条件记录 +SLock 第一条记录对应聚簇索引 +SLock 继续遍历对所有满足条件记录, 先对二级索引 +SLock, 然后对聚簇索引...,就要对查询记录与下一条记录之间加个间隙锁,值得注意的是,这里只需要对二级索引加锁就好了,不需要还另外对主键索引加锁 使用SELECT ......LOCK IN SHARE MODE语句来为记录加锁 对满足条件的二级索引加上 S 型 next-key Lock 然后给对应聚簇索引 + SLock SELECT ......我们都是小青蛙 - MySQL加锁分析三部曲]

    1.4K30

    MySQL更新语句加锁

    这答案也错也对,因为已知条件太少。那么有那些需要已知的前提条件呢? 1、id列是不是主键? 2、当前系统的隔离级别是什么? 3、id列如果不是主键,那么id列上有没有索引呢?...组合三、id不唯一索引+RC 该组合中,id列不在唯一,而是个普通索引,那么当执行sql语句时,MySQL又是如何加锁呢?...对于该组合,MySQL又会进行怎样的加锁呢?看下图: 由于id列上无索引,因此只能走聚簇索引,进行全表扫描。由图可以看出满足条件的记录只有两条,但是,聚簇索引上的记录都会加上X锁。...这样做,保证了最后满足条件的记录加上锁,但是每条记录的加锁操作是不能省略的。 结论:若id列上没有索引,MySQL会走聚簇索引进行全表扫描过滤。由于是在MySQl Server层面进行的。...一条简单的删除语句加锁情况也就分析完成了,但是学习不止于此,还在继续,对于复杂SQL语句又是如何加锁的呢?MySQL中的索引的分析又是怎样的呢?性能分析、性能优化这些又是怎么呢?还需要进一步的学习探索

    2.7K20

    MySQL语句加锁分析详解

    ,加锁顺序和上边语句中的加锁顺序类似,都是先对一条聚簇索引记录加锁后,再给对应的二级索引记录加锁。...之后会继续对number值为15的聚簇索引记录加锁,但是随后InnoDB存储引擎判断它不符合边界条件,随即会释放掉该聚簇索引记录上的锁(注意这个过程中没有对number值为15的聚簇索引记录对应的二级索引记录加锁...这里需要再次强调一下这个语句的加锁顺序: 先对name列为'c曹操'二级索引记录进行加锁。...这个UPDATE语句是先对聚簇索引记录进行加锁,后对二级索引记录进行加锁,如果在不同事务中运行上述两个语句,可能发生一种贼奇妙的事情 —— 事务T2持有了聚簇索引记录的锁,事务T1持有了二级索引记录的锁...不过需要注意一下加锁顺序,对一条二级索引记录加锁完后,会接着对它相应的聚簇索引记录加锁,完后才会对下一条二级索引记录进行加锁,以此类推~ 画个图表示一下就是这样: ?

    1.7K40

    MySQL是如何加锁的?

    这答案也错也对,因为已知条件太少。那么有那些需要已知的前提条件呢?前提一:id列是不是主键?前提二:当前系统的隔离级别是什么?前提三:id列如果不是主键,那么id列上有没有索引呢?...组合三:id不唯一索引+RC该组合中,id列不在唯一,而是个普通索引,那么当执行sql语句时,MySQL又是如何加锁呢?...对于该组合,MySQL又会进行怎样的加锁呢?看下图:由于id列上无索引,因此只能走聚簇索引,进行全表扫描。由图可以看出满足条件的记录只有两条,但是,聚簇索引上的记录都会加上X锁。...这样做,保证了最后满足条件的记录加上锁,但是每条记录的加锁操作是不能省略的。结论:若id列上没有索引,MySQL会走聚簇索引进行全表扫描过滤。由于是在MySQl Server层面进行的。...结论:在MySQL/InnoDB中,所谓的读不加锁,并不适用于所有的情况,而是和隔离级别有关。在Serializable隔离级别下,所有的操作都会加锁。

    54500

    MySQL中InnoDB引擎对索引的扩展

    摘要:InnoDB引擎对索引的扩展,自动追加主键值及其对执行计划的影响。 MySQL中,使用InnoDB引擎的每个表,创建的普通索引(即非主键索引),都会同时保存主键的值。...InnoDB引擎这么做,是用空间换性能,优化器在判断是否使用索引及使用哪个索引时会有更多列参考,这样可能生成更高效的执行计划,获得更好的性能。...下面仅示意走k_d索引的情况: mysql> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G **********...,索引k_d为(d,i1,i2),这时,优化器可以使用最左边的索引前缀(d,i1),生成的执行计划应该类似这样,使用k_d索引找到d为’2000-01-01’及i1为3的1行数据,然后计算count mysql...使用MyISAM引擎的t1myisam表,Handler_read_next值为5,使用InnoDB引擎的t1表,Handler_read_next值减小到1,就是因为InnoDB引擎对索引进行了主键扩展

    1.5K10

    MySQL 加锁和死锁解析

    以下没特殊说明都为RC隔离级别 Insert 无Unique key,插入后 :无论RC或RR隔离级别都是对主键加 LOCK_X+LOCK_REC_NOT_GAP 有Unique key 插入前...Read Committed (RC) ) :Unique Key 唯一约束检查;Purge操作; Repeatable Read (RC ):RC的基础上,所有需要加锁的索引范围扫描和索引查找(Update.../Delete…) 还有一种会加GAP锁:RR隔离级别下,对有唯一索引的表执行insert on duplicate update操作,除了会对新插入的记录加x not gap外,还会对相邻记录加x gap...,能够减少GAP锁导致的死锁(根据业务情况而定) • 原则之三 在MySQL 中,以不同索引的过滤条件, 来操作相同的记录(Update/Delete ),很容易产生死 锁。...-何登成 - 管中窥豹——MySQL(InnoDB)死锁分析之道》

    1.4K20

    MySQL 主键索引在 RR 和 RC 隔离级别下的加锁情况总结

    我今天抽时间给大家总结一个 MySQL InnoDB 存储引擎各种不同 SQL 情况下,加行锁、间隙锁、next-key lock 做一个总结。如果有错误的地方,请大家指正! ?...为了讲清楚相关加锁的情况,我们先来创建一个测试验证用的表。结构如下所示: ? 然后插入几条测试数据。注意,我是在 MySQL 5.7 版本上测试的 ? 在开始之前,我先来解释一下,RR 和 RC。...查询条件是聚簇索引,也就是主键索引的精确匹配情况。 ? 上面这种情况下,如果 SQL 是精确查询,不管是 RR 还是 RC 隔离级别下,都会在命中的索引上加 record lock(行锁)。...注意,行锁不是加在记录上的,而是加在索引上的! 第二种情况,如果是范围查询,那么在在 RC 隔离级别下,会在所有命中的行的聚簇索引上加 record locks(锁行)。...第三种情况,在 RR 隔离级别下,会在所有命中的行的聚簇索引上加 next-key locks(锁住行和间隙)。最后命中的索引的后一条记录,也会被加上 next-key lock。 ?

    2.4K40

    面试官:谈谈你对 MySQL 索引的认识?

    我曾经写过一篇《面试官:讲讲mysql表设计要注意啥》,当时写完后,似乎效果还行! 于是呢,决定再来一个mysql的数据库专题,这篇我们就来谈谈关于索引方面的mysql面试题。...这个时候,参照如下规则建立索引 (1)索引并非越多越好,大量的索引不仅占用磁盘空间,而且还会影响insert,delete,update等语句的性能 (2)避免对经常更新的表做更多的索引,并且索引中的列尽可能少...;对经常用于查询的字段创建索引,避免添加不必要的索引 (3)数据量少的表尽量不要使用索引,由于数据较少,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果 (4)在条件表达式中经常用到不同值较多的列上创建索引...简单来说就是,索引列的唯一值的个数,如果是复合索引就是唯一组合的个数。 这个数值将会作为mysql优化器对语句执行计划进行判定时依据。...如果唯一性太小,那么优化器会认为,这个索引对语句没有太大帮助,而不使用索引。 Cardinality值越大,就意味着,使用索引能排除越多的数据,执行也更为高效。

    1.3K20

    MySQL谬误集01:读不加锁

    我们常常听到一些关于MySQL的说法,比如“读不加锁”,比如“单表数据要小于1000万”,比如“DDL会锁表”等,比如“单表的索引数量应该小于X个”,如果不加思考和测试就直接全盘接受,就可能犯错误,而DB...第1篇文章首先分析下“读不加锁”这种说法是否正确呢? 1.Metadata Locking 若考虑元数据锁(metadata lock),读不加锁错误 。...MySQL5.5引入了metadata lock,对所有查询都会加表锁(包括非事务引擘)。...=test --mysql-user=xxx --mysql-password='xxx' --mysql-host='127.0.0.1' --mysql-port=3306 --max-time=50...总结 MySQL读不加锁是有条件的: 所有读取都会加Metadata Lock MyISAM引擘会加表锁 INNODB引擘读不加锁是利用MVCC实现的 Serializable隔离级别会对所有读取的行加锁

    77132

    mysql 前缀索引_MySQL前缀索引

    有时候需要索引很长的字符字段列,这会增加索引的存储空间以及降低索引的查询效率,一种策略是可以使用哈希索引,还有一种就是使用前缀索引。...前缀索引是选择字符列的前n个字符作为索引,这样可以大大节约索引空间,从而提高索引效率。...前缀索引的选择性 使用前缀索引,在一些场景下可能使得重复的索引值变多,索引的选择性变低,查找时需要过滤更多的行,因此建立前缀索引也要考虑前缀的索引选择性不能太低。...MySQL 无法使用前缀索引做 ORDER BY 和 GROUP BY , 也无法使用前缀索引做覆盖扫描。...后缀索引 MySQL 没有提供后缀索引,事实上,一些业务场景对后缀匹配选择性更高,比如我曾经参与过的项目,手机的入网标示imei号,前缀都是86等固定的国家编号开头,这个时候可以将字符反转后存储,就可以建立选择性较高的前缀索引

    7.1K30

    面试官:谈谈你对mysql索引的认识?

    这个时候,参照如下规则建立索引 (1)索引并非越多越好,大量的索引不仅占用磁盘空间,而且还会影响insert,delete,update等语句的性能 (2)避免对经常更新的表做更多的索引,并且索引中的列尽可能少...;对经常用于查询的字段创建索引,避免添加不必要的索引 (3)数据量少的表尽量不要使用索引,由于数据较少,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果 (4)在条件表达式中经常用到不同值较多的列上创建索引...InnoDB 从 1.0.x 版本开始引入了 Change Buffer,可以算是对 Insert Buffer 的升级。...简单来说就是,索引列的唯一值的个数,如果是复合索引就是唯一组合的个数。 这个数值将会作为mysql优化器对语句执行计划进行判定时依据。...如果唯一性太小,那么优化器会认为,这个索引对语句没有太大帮助,而不使用索引。 Cardinality值越大,就意味着,使用索引能排除越多的数据,执行也更为高效。

    1.1K20

    MySQL死锁系列-常见加锁场景分析

    在上一篇文章《锁的类型以及加锁原理》主要总结了 MySQL 锁的类型和模式以及基本的加锁原理,今天我们就从原理走向实战,分析常见 SQL 语句的加锁场景。...隔离等级对加锁的影响 MySQL 的隔离等级对加锁有影响,所以在分析具体加锁场景时,首先要确定当前的隔离等级。...其中,当前读的 SQL 语句的 where 从句的不同也会影响加锁,包括是否使用索引,索引是否是唯一索引等等。 当前数据对加锁的影响 SQL 语句执行时数据库中的数据也会对加锁产生影响。...聚簇索引,查询命中 聚簇索引就是 InnoDB 存储引擎下的主键索引,具体可参考《MySQL索引》。...而 RC 隔离等级下不需要加锁。 [1240] 无索引 当 Where 从句的条件并不使用索引时,则会对全表进行扫描,在 RC 隔离等级下对所有的数据加排他记录锁。

    2.2K00
    领券