使用next-key locks 用于搜索和索引扫描,可以防止幻读
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所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
随机推荐
- iOS-iPad开发之popoverController使用介绍
iOS-iPad开发之popoverController使用介绍 iOS开发UI篇-popoverController使用注意 iOS SDK:自定义Popover(弹出窗口) 实现的简单例子: // ...
- Arcgis 9.3升级Arcgis10.1需要注重的一点
在项目启动时绑定一个证书文件: 在 Global.asax里面添加 void Application_Start(object sender, EventArgs e) { // Code that ...
- [o] SQLite数据库报错: Invalid column C
向SQLite数据库内新增列,之前出现过报错为提示no such column,通过删除并重建数据库文件解决,这次报错为无效的数据列: java.lang.IllegalArgumentExcepti ...
- jar包的生成及运行
Hello, 大家好,我们见面了,今天是2015年7月30日,我在青岛,你好吗? 这里总结下刚学习到的jar包的生成和运行,网上的资料一搜一大片,我这里总结下适用的 一:jar包的生成: 1:命令行, ...
- mysql 安装-编码
mysql的安装过程相对较为简单,在这里就不阐述,我想说的问题是,关于编码的安装, 在安装到达'Please select the default character set'的时候,选择'Manul ...
- Nginx和Apache共存环境下apache获得真实IP
自从Nginx出现以后,我们都喜欢让 Nginx 跑在前方处理静态文件,然后通过 proxy 把动态请求过滤给 apache.这么有个问题,跑在后方 apache 上的应用获取到的IP都是Nginx所 ...
- OC - 31.通过封装的自定义布局快速实现商品展示
概述 实现效果 设计思路 采用MVC架构,即模型—视图-控制器架构 使用MJExtension框架实现字典转模型 使用MJRefresh框架实现上拉和下拉刷新 上拉刷新,加载新的数据 下拉刷新,加载更 ...
- Linux数据写操作改进
Linux的IO操作中数据的写函数int nwrite = write(int fd,void* buf ,int len)表示向fd文件描述符写入len个字节长度的数据报文,但是这并不能保证真正向内 ...
- Codeforces 551C GukiZ hates Boxes(二分)
Problem C. GukiZ hates Boxes Solution: 假设最后一个非零的位置为K,所有位置上的和为S 那么答案的范围在[K+1,K+S]. 二分这个答案ans,然后对每个人尽量 ...
- 【BZOJ1012】【树状数组求区间最值】最大数maxnumber
Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. ...