參考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. js插件---图片裁剪cropImgBox(适合练习编写插件之用)

    js插件---图片裁剪cropImgBox(适合练习编写插件之用) 一.总结 一句话总结:无论是灰度还是高对比度的图片,都是先处理canvas的像素,使其变成灰度或者高对比度,然后再用canvas.t ...

  2. Cisco交换机端口安全

    Cisco交换机端口安全       通过端口设置,可以限制允许访问交换机上某个端口的MAC地址以及IP(可选)来实现严格控制对该端口的输入,最终确保网络接入安全.配置网络安全时应该注意如下问题: 1 ...

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

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

  4. BZOJ3130: [Sdoi2013]费用流(二分,最大流)

    Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络 ...

  5. Scrapy请求传参

    scrapy.Request(url=url, callback=self.parse_item, meta={'item': item}, headers=headers) url: 要请求的地址 ...

  6. Top 16 Java 应用类 - 这些功能再也不用自己写了

    Java中有很多应用类.这些类定义静态方法能够解决非常多常见的问题.以下是通过5万个开源项目统计得到的最热门的16个应用类. 类按热门程序排列.类的方法也是按热门程序排序. 浏览这个类能够看看有哪些功 ...

  7. 淘宝在hbase中的应用和优化

    本文来自于NoSQLFan联合作者@koven2049,他在淘宝从事Hadoop及HBase相关的应用和优化. 对Hadoop.HBase都有深入的了解,本文就是其在工作中对HBase的应用优化小结, ...

  8. 第一天,Mysql安装,DDL(数据库定义语言),DBA,DML(数据库操纵语言),导入外面的sql文件

    把“D:\mysql-5.6.22-winx64\bin”添加到系统环境变量path中了,然后在任意目录可访问mysql等命令,这样如登录等操作就不需要进入MySQL安装目录才好执行! MySQL下载 ...

  9. es62

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Elasticsearch之shield(权限)插件安装之后的浏览详解

    前期博客 Elasticsearch-2.4.3的3节点安装(多种方式图文详解)(含 head.kopf.marvel.shield和watcher插件安装和使用) 访问es:-u es_admin ...