Next-Key Locks

一个next-key lock 是 一个record lock 在index record 和 一个区间锁 在一个区间在index record之前

InnoDB 执行 row-level locking  以这样一种方式当它搜索或者扫描 一个表的索引,

它设置共享或者排它锁在index records.

因此, row-level locks 实际上是  index-record locks. 

一个next-key lock 在一个index record 也影响区间在那个index record 之前。

也就是说,一个next-key lock  是一个Index-record 加上一个区间锁在index record 之前的区间。

如果一个会话有一个共享或者排它锁在记录R上在一个索引上,

另外的会话不能插入一个新的index record 在这个区间 

假设一个Index 包含值10,11,13,20.

可能的next-key locks 对于这个index包含了下面的时间间隔,

一个圆括号表示排除间隔端点

一个方括号表示包含间隔端点

(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity) 在最后的区间, next-key lock locks 的区间在最大值的上界在index和上界的伪记录 有一个值高于任何值在index里。 上界限不是一个真正的index record.所以,实际上, next-key lock locks只有区间在最大索引值后面的区间 默认情况下, InnoDB 工作在REPEATABLE READ 事务隔离级别下 innodb_locks_unsafe_for_binlog 系统变量被禁用, 在那种情况下,可以使用next-key locks来搜索和索引扫描,来防止幻读行 Session 1: mysql> explain select * from t1 where id BETWEEN 5 and 7 for update;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+
| 1 | SIMPLE | t1 | range | t1_idx1 | t1_idx1 | 5 | NULL | 3 | Using index condition |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+
1 row in set (0.00 sec) mysql> select * from t1 where id BETWEEN 5 and 7 for update;
+-----+------+------+
| sn | id | info |
+-----+------+------+
| 239 | 5 | a5 |
| 240 | 6 | a6 |
| 241 | 7 | a7 |
+-----+------+------+
3 rows in set (0.00 sec) Session 2:
mysql> update t1 set id=300 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> rollback;
Query OK, 0 rows affected (0.01 sec) mysql> update t1 set id=500 where id=5;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update t1 set id=600 where id=6;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update t1 set id=600 where id=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> rollback;
Query OK, 0 rows affected (0.00 sec) mysql> update t1 set id=600 where id=7;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update t1 set id=800 where id=8;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update t1 set id=800 where id=9;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> rollback;
Query OK, 0 rows affected (0.01 sec) 会锁住 5,6,7,8 4条记录 继续测试: Session 1:
mysql> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t1 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
| t1 | 0 | t1_idx1 | 1 | id | A | 11 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec) mysql> select * from t1 where id=7 for update;
+-----+------+------+
| sn | id | info |
+-----+------+------+
| 241 | 7 | a7 |
+-----+------+------+
1 row in set (0.00 sec) Session 2:
mysql> update t1 set id=800 where id=8;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> rollback;
Query OK, 0 rows affected (0.01 sec) 去掉Id列的索引继续测试: Session 1: mysql> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t1 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
| t1 | 0 | t1_idx1 | 1 | id | A | 11 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec) mysql> alter table t1 drop index t1_idx1;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t1 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec) mysql> select * from t1 where id=7 for update;
+-----+------+------+
| sn | id | info |
+-----+------+------+
| 241 | 7 | a7 |
+-----+------+------+
1 row in set (0.00 sec) Session 2: Database changed
mysql> update t1 set id=800 where id=8; --HANG /************************************************
mysql> explain select * from t1 where id=7 for update;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec) mysql> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t1 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
| t1 | 1 | t1_idx1 | 1 | id | A | 11 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec) mysql> explain select * from t1 where id=7 for update;
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | t1 | ref | t1_idx1 | t1_idx1 | 5 | const | 1 | NULL |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec) 下面来举个手册上的例子看什么是next-key lock。假如一个索引的行有10,11,13,20
那么可能的next-key lock的包括:
(无穷小, 10]
(10,11]
(11,13]
(13,20]
(20, 无穷大) (这里无穷大为什么不是闭合?你数学不到家~~) 举例测试: mysql> desc t100;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| sn | int(11) | NO | PRI | NULL | auto_increment |
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.00 sec) mysql> show create table t100\G;
*************************** 1. row ***************************
Table: t100
Create Table: CREATE TABLE `t100` (
`sn` int(11) NOT NULL AUTO_INCREMENT,
`id` int(11) DEFAULT NULL,
PRIMARY KEY (`sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec) ERROR:
No query specified Session 1:
mysql> mysql> show index from t100;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t100 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec) mysql> select * from t100;
+----+------+
| sn | id |
+----+------+
| 1 | 7 |
| 2 | 9 |
| 3 | 10 |
| 4 | 12 |
| 5 | 13 |
| 6 | 14 |
| 7 | 15 |
| 8 | 22 |
| 9 | 23 |
| 10 | 24 |
| 11 | 25 |
+----+------+
11 rows in set (0.00 sec) mysql> update t100 set id=100 where id=1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0 id列上没有索引,导致: Session 2: mysql> insert into t100(id) values(100); t100表所有记录锁住 /*************** mysql> show index from t100;
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t100 | 0 | PRIMARY | 1 | sn | A | 11 | NULL | NULL | | BTREE | | |
| t100 | 1 | t1oo_idx1 | 1 | id | A | 11 | NULL | NULL | YES | BTREE | | |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ mysql> select * from t100;
+----+------+
| sn | id |
+----+------+
| 1 | 7 |
| 2 | 9 |
| 3 | 10 |
| 4 | 12 |
| 5 | 13 |
| 6 | 14 |
| 7 | 15 |
| 8 | 22 |
| 9 | 23 |
| 10 | 24 |
| 11 | 25 |
+----+------+
11 rows in set (0.00 sec) mysql> delete from t100 where id=21;
Query OK, 0 rows affected (0.00 sec) Session 2: mysql> insert into t100(id) values (15);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into t100(id) values (16);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into t100(id) values (17);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> mysql> insert into t100(id) values (18);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into t100(id) values (19);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into t100(id) values (20);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into t100(id) values (21);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 锁15-21 之间 行锁加锁对象永远是索引记录,因为innodb中表即索引
在(三)种,a=21也是不存在,但是在表里面21前后都有记录,因此这里next-key lock的区间也就是(15,21],因此不在这个区间内的都可以插入。 记录锁---锁单条记录;区间锁---锁一个开区间;next-key 锁---前面两者的结合

Next-Key Locks的更多相关文章

  1. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  2. 学习总结---INNODB 事务并发

    目前在做一个OLTP的数据库系统,批量读写和随机读写并发,情况比较复杂.INNODB是我们的MYSQL引擎,他的主要特点是读操作可以不受阻塞,而修改操作会加锁.如何才能最高效的使用innodb是我们需 ...

  3. Java模拟按键

    JDK自带了Robot类,此类用于为测试自动化.自运行演示程序和其他需要控制鼠标和键盘的应用程序生成本机系统输入事件.Robot 的主要目的是便于 Java 平台实现自动测试. 详情可查看jdk1.6 ...

  4. InnoDB锁冲突案例演示

      Preface       As we know,InnoDB is index organized table.InnoDB engine supports row-level lock bas ...

  5. InnoDB意向锁和插入意向锁

      Preface       Last night one buddy in tech wechat group asked "what's intention locks of Inno ...

  6. Microsoft SQL Server Version List [sqlserver 7.0-------sql server 2016]

    http://sqlserverbuilds.blogspot.jp/   What version of SQL Server do I have? This unofficial build ch ...

  7. Microsoft SQL Server Version List(SQL Server 版本)

    原帖地址 What version of SQL Server do I have? This unofficial build chart lists all of the known Servic ...

  8. Dubbo(四):深入理解Dubbo核心模型Invoker

    一.Dubbo中Invoker介绍 为什么说Invoker是Dubbo核心模型呢? Invoker是Dubbo中的实体域,也就是真实存在的.其他模型都向它靠拢或转换成它,它也就代表一个可执行体,可向它 ...

  9. SqlServer 版本号

    RTM (no SP) SP1 SP2 SP3 SP4 SQL Server 2014      codename Hekaton  12.00.2000.8 SQL Server 2012      ...

  10. Dubbo 服务引入-Version2.7.5

    1.服务引用原理 Dubbo 服务引用的时机有两个,第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务,第二个是在 Referen ...

随机推荐

  1. 【转】linux下 postgres的一些操作总结

    参考博文: PostgreSQL详解     1. 基本操作命令 安装完成后,PostgreSQL默认创建了名为postgres数据库用户账户,其与MySQL的root以及SQL Server的sa账 ...

  2. 利用xshell密钥管理服务器远程登录+VIM dd命令操作之伤之再伤

    1.打开Xshell界面,中文界面方便操作,菜单栏:工具——新建用户密钥生成向导 2.密钥类型选择RSA,密钥长度选择2048位,单击下一步继续: 3.很快生成公钥对,单击下一步继续: 4.密钥名称可 ...

  3. 获取CPU序列号

    public string GetCPUSerialNo() { string cpuSerialNo = string.Empty; ManagementClass managementClass ...

  4. WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构

    原文:WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构 细算起来,已经有好几个月没有真正的写过文章了.近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析>的写作,一直 ...

  5. perl use base 代替 @ISA

    packge Mule; use base ("Horse", "donkey"); # 声明一个超类 它是下面东西的缩写: package Mule; BEG ...

  6. perl 使用SUPER类来访问覆盖的方法

    有时候,你希望一个衍生类的方法表现得象基类中的某些方法的封装器 这就是 SUPER 伪类提供便利的地方.它令你能够调用一个覆盖了的基类方法,而不用声明 是哪个类定义了该方 法.(注:不要把这个和第十一 ...

  7. 基于visual Studio2013解决C语言竞赛题之1048打印矩阵

      题目 解决代码及点评 /* 48. 找规律填写N×N方阵.如N=8时, 其方阵为: */ #include <stdio.h> #include <stdlib.h& ...

  8. hdu2489 Minimal Ratio Tree

    hdu2489 Minimal Ratio Tree 题意:一个 至多  n=15 的 完全图 ,求 含有 m 个节点的树 使 边权和 除 点权和 最小 题解:枚举 m 个 点 ,然后 求 最小生成树 ...

  9. [poj 1904]King's Quest[Tarjan强连通分量]

    题意:(当时没看懂...) N个王子和N个女孩, 每个王子喜欢若干女孩. 给出每个王子喜欢的女孩编号, 再给出一种王子和女孩的完美匹配. 求每个王子分别可以和那些女孩结婚可以满足最终每个王子都能找到一 ...

  10. [Java聊天室server]实战之二 监听类

    前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...