參考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. 10.ng-class-even与ng-class-odd

    转自:https://www.cnblogs.com/best/tag/Angular/ AngularJS模板使你可以把该作用域内的数据直接绑定到所显示的HTML元素 ng-class-even与n ...

  2. BZOJ 1306 DFS

    思路: 搜索就好 (注意不要枚举太多东西) //By SiriusRen #include <cstdio> using namespace std; int n,point[10],an ...

  3. 是时候抛弃web.xml了?

    你是否再为配置文件web.xml容易出错而烦恼?是否为web.xml文件存放位置而不知所措?是否为web.xml为什么要这样配?怎么才能更好的配置web.xml而烦恼?那么一种新的方式出现了: spr ...

  4. [Usaco2009 Feb]Stock Market 股票市场 完全背包

    Code: #include<cstdio> #include<algorithm> #include<iostream> #include<cstring& ...

  5. selenium 窗口句柄之间的切换

    以前使用selenium时都是在单窗口的模式下,本次新增多窗口下的窗口之间切换 from selenium import webdriver from selenium.webdriver.commo ...

  6. BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...

  7. 学习《人工智能一种现代的方法(第3版)》中文PDF+英文PDF

    学习人工智能概论时,推荐看看<人工智能:一种现代的方法(第3版)>,最权威.最经典的人工智能教材,已被全世界100多个国家的1200多所大学用作教材. 全面性以及结构的安排还是不错的,值得 ...

  8. Swift学习笔记(2)--元组(Tuples)、Optional(可选值)、(Assertions)断言

    1.Tuples(元组) 元组是多个值组合而成的复合值.元组中的值可以是任意类型,而且每一个元素的类型可以是不同的. 1>定义:使用()包含所有元素,用逗号分开,也可以对每个元素做命名 let ...

  9. android与C# WebService基于ksoap通信(C#篇)

    1.打开VS 2013新建项目>>ASP.NET空WEB应用程序(我用的是.net 4.0) 2.在刚建立的项目上加入新建项(WebService) 这时TestService的代码例如以 ...

  10. cgroups

    CGROUPS官方解析,用户空间怎样监控 http://blog.chinaunix.net/uid-16763274-id-2103750.html cgroups概念 fr=aladdin&quo ...