參考http://blog.csdn.net/zbszhangbosen/article/details/7434637#reply

这里补充一些:

(1)InnoDB默认加锁方式是next-key locking

(2)在聚集索引中,假设主键有唯一性约束(unique,auto increment),next-key locking 会自己主动降级为record locking。

(3)因为事务的隔离性和一致性要求,会对全部扫描到的record加锁。

比方:update ... where/delete .. where/select ...from...lock in share mode/ select .. from .. for update这都是next-key lock。

(4)注意优化器的选择。

包含聚集索引和辅助索引。有时会用全表扫描替代索引扫描。这时整张表(聚集索引表)都会被加锁。

record lock:记录锁,也就是只锁着单独的一行

gap lock:区间锁。只锁住一个区间(注意这里的区间都是开区间。也就是不包含边界值,至于为什么这么定义?innodb官方定义的)

next-key lock:record lock+gap lock,所以next-key lock也就半开半闭区间,且是下界开,上界闭。(为什么这么定义?innodb官方定义的)

以下来举个手冊上的样例看什么是next-key lock。

假如一个索引的行有10,11,13,20

那么可能的next-key lock的包含:

(无穷小, 10]

(10,11]

(11,13]

(13,20]

(20, 无穷大) (这里无穷大为什么不是闭合?你数学不到家~~)

好了如今通过举样例说明:





表test

mysql> show create table test;

+-------+--------------------------------------------------------------------------------------------------------+

| Table | Create Table                                                                                           |

+-------+--------------------------------------------------------------------------------------------------------+

| test  | CREATE TABLE `test` (

  `a` int(11) NOT NULL,

  PRIMARY KEY (`a`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

+-------+--------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select * from test;

+----+

| a  |

+----+

| 11 |

| 12 |

| 13 |

| 14 |

+----+

4 rows in set (0.00 sec)

開始实验:

(一)

session 1:

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)





mysql> delete from test where a=11;

Query OK, 1 row affected (0.00 sec)





session 2:

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)





mysql> insert into test values(10);

Query OK, 1 row affected (0.00 sec)





mysql> insert into test values(15);

Query OK, 1 row affected (0.00 sec)





mysql> insert into test values(9);

Query OK, 1 row affected (0.00 sec)





mysql> insert into test values(16);

Query OK, 1 row affected (0.01 sec)





mysql> rollback;

Query OK, 0 rows affected (0.00 sec)





ok,上面的情况是预期的。由于a上有索引。那么当然就仅仅要锁定一行,所以其它行的插入不会被堵塞。

那么接下来的情况就有意思了

(二)

session 1(跟上一个session 1同样):

delete from test where a=22;

Query OK, 0 rows affected (0.01 sec)





session 2:

mysql> insert into test values (201);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (20);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (19);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (18);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (16);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (9);

Query OK, 1 row affected (0.00 sec)





从上面的结果来看,在a=11后面全部的行,也就是区间(11,无穷大)都被锁定了。先不解释原因,再来看一种情况:

(三)

session 1:

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)





mysql> select * from test;

+----+

| a  |

+----+

|  7 |

|  9 |

| 10 |

| 12 |

| 13 |

| 14 |

| 15 |

| 22 |

| 23 |

| 24 |

| 25 |

+----+

11 rows in set (0.00 sec)





mysql> delete from test where a=21;

Query OK, 0 rows affected (0.00 sec)





session 2:

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)





mysql> insert into test values (20);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (26);

Query OK, 1 row affected (0.00 sec)





mysql> insert into test values (21);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (16);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into test values (6);

Query OK, 1 row affected (0.01 sec)





从这里能够看出。如今被锁住的区间就仅仅有[16,21)了。

有了前面对三种类型的加锁解释,如今能够来解释为什么会这样了,在innodb表中 delete from where ..针对扫描到的索引记录加next-key锁(详细的什么语句加什么锁能够查看手冊,另外须要说明一下。行锁加锁对象永远是索引记录,由于innodb中表即索引) 。

在(一)中。实际上加的next-key lock就是(11,11] 因此也仅仅有a=11这一条记录被锁住。其它全部插入都没有关系。

在(二)中,由于a=22这条记录不存在,并且22比表里全部的记录值都大,所以在innodb看来锁住的区间就是(14, 无穷大)。

所以在插入14以后的值都提示被锁住,而14之前的则能够。

在(三)种。a=21也是不存在,可是在表里面21前后都有记录。因此这里next-key lock的区间也就是(15,21],因此不在这个区间内的都能够插入。

那么为什么next-key lock都是下界开区间。上界闭区间呢?这个倒不重要,管它呢,可是有一点我个人却认为比較怪,比方说

delete test where a > 11           #------- 1

它的next-key lock是(11, 无穷大) 

delete test where a < 11           #------- 2

它的next-key lock是(无穷小, 10]

这样给人的感觉就非常怪。由于在手冊上对next-key lock的定义:

Next-key lock: This is a combination of a record lock on the index record and a gap lock on the gapbefore the index record.

而在1那种情况下,如果依照手冊上的解释,记录锁和它之前的gap那么就会有些牵强。

[今天再次看了一遍官方手冊,是之前自己的理解不到位,这个before是对的,由于innodb在加锁时是全部扫描过程中遇到的记录都会被加锁,那么对于1那种情况,实际上是从12開始扫描,可是由于要保证a>11的都被delete掉。因此得一直扫描下去那自然最大值就是无穷大,由于这个next-key lock就是无穷大这条记录(这是如果的一条记录,表示一个边界)加上它之前的gap lock (11, 无穷大),所以在不论什么时候next-lock都是record
lock加上这个record之前的一个gap lock]

可是仅仅要我们自己能理解即可了:记录锁---锁单条记录。区间锁---锁一个开区间。next-key 锁---前面两者的结合,而不要管什么before。

另外next-key lock尽管在非常多时候是锁一个区间,但要明确一个区间也可能仅仅有一个元素。因此在称delete from tb where key=x 这样的情况下加next-key锁也是全然正确的。

另外还提两点:

1.假设我们的SQL语句里面没有利用到索引。那么加锁对象将是全部行(但不是加表锁)。所以建索引是非常重要的

2.next-key lock是为防止幻读的发生,而仅仅有repeatable-read以及以上隔离级别才干防止幻读。所以在read-committed隔离级别以下没有next-key lock这一说法。

innodb next-key lock解析的更多相关文章

  1. InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析

    InnoDB锁机制之Gap Lock.Next-Key Lock.Record Lock解析 有意思,解释的很好

  2. 关于InnoDB的Next-Key lock

    最近一段时间在准备新员工培训的材料,本来打算介绍介绍概念就OK的,但是既然写了事务的章节,就特别想介绍一下锁,介绍了锁,就忍不住想介绍一下Next-Key Lock. 大家知道,标准的事务隔离级别有R ...

  3. Key lock 的秘密

    研究死锁,或者观察sp_lock,有时候最恼人的莫过于你看到下面研究成果的key lock,但是却不知道究竟是哪个page 哪个row被lock住了: Exec sp_lock:   就说上面的key ...

  4. mysql之 [ERROR] InnoDB: Unable to lock ./ibdata1, error: 11

    问题描述:启动MySQL后,出现连接不上,报 [ERROR] InnoDB: Unable to lock ./ibdata1, error: 11[root@mysql01 ~]# service ...

  5. MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析

    MySQL InnoDB支持三种行锁定方式: l   行锁(Record Lock):锁直接加在索引记录上面,锁住的是key. l   间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙 ...

  6. my39_InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析

    MySQL InnoDB支持三种行锁定方式: 行锁(Record Lock):锁直接加在索引记录上面,锁住的是key. 间隙锁(Gap Lock): 锁定索引记录间隙,确保索引记录的间隙不变.间隙锁是 ...

  7. 从ext4将mysql数据目录移动至lustre出现(InnoDB: Unable to lock ./ibdata1, error: 38.)

    因为数据目录过大,因此我把目录从本地移到了共享存储中.在修改了/etc/my.cnf和/etc/init.d/mysqld之后发现数据库可以运行,但启动速度很慢 原因是原文件系统是ext4,而目标文件 ...

  8. MySQL InnoDB primary key根节点常驻内存

    mysql的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要1~3次磁盘I/O操作.

  9. MySQL · 引擎特性 · InnoDB index lock前世今生

    http://mysql.taobao.org/monthly/2015/07/05/ MySQL · 引擎特性 · InnoDB index lock前世今生 前言 InnoDB并发过程中使用两类锁 ...

随机推荐

  1. JavaWeb简单介绍

    服务器端编程 技术种类 Servlet JSP Struts Spring Hibernate EJB Web Service Web服务器 IIS Apache Tomcat (提供对JSP和Ser ...

  2. 之前写的收集的一些c++代码片,算法排序,读文件,写日志,快速求积分等等

    写日志: class LogFile { public: static LogFile &instance(); operator FILE *() const { return m_file ...

  3. Ubuntu源配置

    一.图形界面配置 新手推荐使用图形界面配置: 系统工具 -> 软件和更新-> Ubuntu软件-> 下载自:-> 其他站点  点击 选择最佳服务器(将通过连接测试确定最佳镜像) ...

  4. 关于echarts3版本里的tree图形显示Bug、无法缩放和移动

    在使用echarts3版本的js绘制tree图表的时候,如果想动态更新tree的数据,可能会出现图表渲染有异常,并且api给出的roam配置无法控制图表通过鼠标缩放和移动,如下图: 不过更改echar ...

  5. Js中的数据类型--String

    昼猫笔记--给你带来不一样的笔记 不止是笔记 更多的是思考 上一期咱们大概了解了下什么是JavaScript,想必大家也都知道 今天主要说下Js中的数据类型 在Js中一共分为六种数据类型 其中基本数据 ...

  6. tensorflow学习之路-----MNIST数据

    ''' 神经网络的过程:1.准备相应的数据库 2.定义输入成 3.定义输出层 4.定义隐藏层 5.训练(根据误差进行训练) 6.对结果进行精确度评估 ''' import tensorflow as ...

  7. python编写PAT 1007 Maximum Subsequence Sum(暴力 分治法 动态规划)

    python编写PAT甲级 1007 Maximum Subsequence Sum wenzongxiao1996 2019.4.3 题目 Given a sequence of K integer ...

  8. jQuery判断字符串是否含有中文字符

    //判断字符串是不是中文String.prototype.isChinese = function () {    var reg = /[^\x00-\xff]/ig;//判断是否存在中文和全角字符 ...

  9. 一个project师该怎样高效工作

    1.  静. 在千头万绪,百般push.各种IM电话邮件狂轰滥炸中保持一个静字.找到最适合如今做的事情,情绪不要被外界所干扰.一次仅仅做一件事,不要被打断. 有的公司土鳖文化严重,领导一会儿要求你干这 ...

  10. ExtAspNet依据Grid导出Excel

    protected void Button1_Click(object sender, EventArgs e) { Response.ClearContent(); Response.AddHead ...