Next-Key Locks A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record. 是一个记录锁在索引记录上和一个区间锁在区间的组合 在index record之前 InnoDB 执行行级锁以这种方式 当它搜索或者扫描一个表的索引,它设置共享或者排它锁在Index records。 因此, row-level locks 实际上是 index-record locks. 一个 next-key lock 在一个index record 也会影响 那个index record 记录前的gap 也就是说 一个next-key lock 是一个 index-record lock plus a gap lock If one session has a shared or exclusive lock on record R in an index, another session cannot insert a new index record in the gap immediately before R in the index order. 如果一个session 有一个共享或者排它锁在记录R上,另外的session 不能插入新的index record 在before R这个区间 Session 1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> update SmsTest set phoneNo=111 where phoneNo <10;
Query OK, 20 rows affected (0.01 sec)
Rows matched: 20 Changed: 20 Warnings: 0 mysql> explain update SmsTest set phoneNo=111 where phoneNo <10;
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
| 1 | SIMPLE | SmsTest | range | SmsTest_idx1 | SmsTest_idx1 | 4 | const | 20 | Using where; Using temporary |
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
1 row in set (0.00 sec) 锁住1-9的记录 mysql> select * from SmsTest where phoneNo <10;
+-------+---------+-------------+--------+
| sn | phoneNo | channelType | status |
+-------+---------+-------------+--------+
| 1 | 1 | 2 | 1 |
| 45210 | 1 | 1 | 1 |
| 45211 | 1 | 1 | 1 |
| 2 | 2 | 2 | 1 |
| 201 | 2 | 1 | 1 |
| 45212 | 2 | 1 | 1 |
| 3 | 3 | 2 | 1 |
| 45209 | 3 | 1 | 1 |
| 45213 | 3 | 1 | 1 |
| 4 | 4 | 2 | 1 |
| 45214 | 4 | 1 | 1 |
| 5 | 5 | 2 | 1 |
| 45215 | 5 | 1 | 1 |
| 6 | 6 | 2 | 1 |
| 45216 | 6 | 1 | 1 |
| 7 | 7 | 2 | 1 |
| 45217 | 7 | 1 | 1 |
| 8 | 8 | 2 | 1 |
| 45218 | 8 | 1 | 1 |
| 9 | 9 | 2 | 1 |
+-------+---------+-------------+--------+
20 rows in set (0.00 sec) Session 2: mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(1,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(2,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(3,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(4,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(5,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(6,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(7,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(8,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(9,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(10,1,1);
Query OK, 1 row affected (0.01 sec) mysql>
mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(11,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(12,1,1);
Query OK, 1 row affected (0.01 sec) 假设一个Index 包含值10,11,13和20,可能的next-key locks 对于这个索引覆盖下面的区间, 一个圆括号表示排除两端,一个方块号报表包含 (negative infinity, 10] 负无穷大
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)正无穷大 测试:
mysql> select * from SmsTest where phoneNo in (10,11,13,20);
+-------+---------+-------------+--------+
| sn | phoneNo | channelType | status |
+-------+---------+-------------+--------+
| 10 | 10 | 2 | 1 |
| 45239 | 10 | 1 | 1 |
| 45252 | 10 | 1 | 1 |
| 11 | 11 | 2 | 1 |
| 45253 | 11 | 1 | 1 |
| 13 | 13 | 2 | 1 |
| 20 | 20 | 2 | 1 |
+-------+---------+-------------+--------+
7 rows in set (0.00 sec) mysql> update SmsTest set phoneNo=999 where phoneNo in (10,11,13,20);
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7 Changed: 7 Warnings: 0 mysql> explain update SmsTest set phoneNo=999 where phoneNo in (10,11,13,20);
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
| 1 | SIMPLE | SmsTest | range | SmsTest_idx1 | SmsTest_idx1 | 4 | const | 7 | Using where; Using temporary |
+----+-------------+---------+-------+---------------+--------------+---------+-------+------ +------------------------------+
1 row in set (0.00 sec) Session 2: mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(1,1,1);
Query OK, 1 row affected (0.01 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(2,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(3,1,1);
Query OK, 1 row affected (0.05 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(4,1,1);
Query OK, 1 row affected (0.01 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(5,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(6,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(7,1,1);
Query OK, 1 row affected (0.01 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(8,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(9,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(10,1,1);--hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(11,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(12,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(13,1,1);--hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(14,1,1);
Query OK, 1 row affected (0.01 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(15,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(16,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(17,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(18,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(19,1,1); mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(20,1,1); --hang mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(21,1,1);
Query OK, 1 row affected (0.01 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(22,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.SmsTest(PhoneNo,channelType,status) values(23,1,1);
Query1 row affected (0.01 sec) 默认情况下,InnoDB 操作在 REPEATABLE READ transaction isolation level 禁用innodb_locks_unsafe_for_binlog system variable 在这种情况下,使用next-key locks 用于搜索和索引扫描,可以防止幻读
使用next-key locks 用于搜索和索引扫描,可以防止幻读的更多相关文章
-
Orchard搜索与索引
Orchard提供了索引与搜索的功能.开启Indexing属性可实现索引功能,伴随着一个特定的索引执行(默认包含基础搜索引擎).除了Indexing和Search提供查询索引的功能外(通过关键字或使用 ...
-
Key Lookup开销过大导致聚集索引扫描
以前总结过一篇文章SQL SERVER中什么情况会导致索引查找变成索引扫描 介绍了几种索引查找(Index Seek)变成索引扫描(Index Scan)的情形.昨天写一篇文章的时候,也遇到了一个让人 ...
-
SQL SERVER中什么情况会导致索引查找变成索引扫描
SQL Server 中什么情况会导致其执行计划从索引查找(Index Seek)变成索引扫描(Index Scan)呢? 下面从几个方面结合上下文具体场景做了下测试.总结.归纳. 1:隐式转换会导致 ...
-
mysql使用索引扫描来做排序
mysql有两种方式可以生成有序的结果,通过排序操作或者按照索引顺序扫描,如果explain的type列的值为index,则说明mysql使用了索引扫描来做排序(不要和extra列的Using ind ...
-
Oracle 表的访问方式(2)-----索引扫描
索引扫描(Index scan) 我们先通过index查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这种查找方式称为索引扫描或索引 ...
-
MySQL优化GROUP BY-松散索引扫描与紧凑索引扫描
满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有).在某些情况中,MySQL能够做得更好,即通过索引 ...
-
Index Scans 索引扫描
官方文档链接地址 http://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CNCPT1170 Index Scans 在索 ...
-
AppBoxFuture: 二级索引及索引扫描查询数据
数据库索引对于数据查询的重要性不可言喻,因此作者在存储层实现了二级索引,以及利用索引进行扫描的功能.目前仅实现了分区表与非分区表的本地索引(数据与索引共用一个Raft组管理),全局索引及反向索引待 ...
-
Oracle索引梳理系列(八)- 索引扫描类型及分析(高效索引必备知识)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
随机推荐
-
Merge k Sorted Lists
1. Merge Two Sorted Lists 我们先来看这个 问题: Merge two sorted linked lists and return it as a new list. The ...
-
Python之路-python(html、css)
html: 概述: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样 ...
-
PostgreSQL9.2.4内核源码结构介绍
PostgreSQL的源代码可以随意获得,其开源协议也允许研究者任意修改,这里介绍一下PostgreSQL的源码结构以及部分实现机制.下载PostgreSQL源代码并减压后,其一级目录结构如下图: P ...
-
Python爬虫(十四)_BeautifulSoup4 解析器
CSS选择器:BeautifulSoup4 和lxml一样,Beautiful Soup也是一个HTML/XML的解析器,主要的功能也是如何解析和提取HTML/XML数据. lxml只会局部遍历,而B ...
-
json_decode($str,true)的结果为null
//$result为传进来的json值 $result = $this->params['auth_result']; //html_entity_decode进行HTML 实体转换为字符 // ...
-
springboot 零xml集成mybatis-plus
工程结构 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...
-
CentOS7实现RabbitMQ高可用集群
CentOS安装RabbitMQ集群 1.有3台已安装RabbitMQ的机器 192.168.38.133 rabbitmq1 192.168.38.137 rabbitmq2 192.168.38. ...
-
省队集训Day1 睡觉困难综合征
传送门:https://www.luogu.org/problem/show?pid=3613 [题解] 按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做. 写棵LCT,维护正反两种权值, ...
-
开始使用Bootstrap
bootstrap使用到的图标字体文件格式有 .woff,IIS7下需要添加MIME映射:.woff application/x-font-woff
-
May 6th 2017 Week 18th Saturday
A great ship asks deep water. 巨轮寻深水而航行. A great ship needs deep water so as to get enough buoyancy t ...