Mysql加锁过程详解(7)-初步理解MySQL的gap锁
初步理解MySQL的gap锁
初识MySQL的gap,觉得这个设计比较独特,和其他数据库的做法不太一样,所以整理一个简单的memo(虽然关于gap锁,相关资料已经很多了)
1. 什么是gap
A place in an InnoDB index data structure where new values could be inserted.
说白了gap就是索引树中插入新记录的空隙。相应的gap lock就是加在gap上的锁,还有一个next-key锁,是记录+记录前面的gap的组合的锁。
2. gap锁或next-key锁的作用
http://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html
To prevent phantoms, InnoDB uses an algorithm called next-key locking that combines index-row
locking with gap locking. InnoDB performs row-level locking in such a way that when it searches
or scans a table index, it sets shared or exclusive locks on the index records it encounters.
Thus, the row-level locks are actually index-record locks. In addition, a next-key lock on
an index record also affects the “gap” before that index record. That is, a next-key lock is
an index-record lock plus a gap lock on the gap preceding the index record. 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.
简单讲就是防止幻读。通过锁阻止特定条件的新记录的插入,因为插入时也要获取gap锁(Insert Intention Locks)。
3. 什么时候会取得gap lock或nextkey lock
这和隔离级别有关,只在REPEATABLE READ或以上的隔离级别下的特定操作才会取得gap lock或nextkey lock。
http://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html
2.1 REPEATABLE READ
... For consistent reads, there is an important difference from the READ COMMITTED isolation level:
All consistent reads within the same transaction read the snapshot established by the first read. ... For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE), UPDATE, and DELETE statements,
locking depends on whether the statement uses a unique index with a unique search condition,
or a range-type search condition. For a unique index with a unique search condition,
InnoDB locks only the index record found, not the gap before it. For other search conditions,
InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions
by other sessions into the gaps covered by the range.
locking reads,UPDATE和DELETE时,除了对唯一索引的唯一搜索外都会获取gap锁或next-key锁。即锁住其扫描的范围。
下面对非唯一索引做个测试。
表定义如下:
mysql> show create table tb2;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
| tb2 | CREATE TABLE `tb2` (
`id` int(11) DEFAULT NULL,
`c1` int(11) DEFAULT NULL,
KEY `tb2_idx1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
注意id只是索引,不是主键
表中有3条记录: 10,20,30。
mysql> select * from tb2;
+------+------+
| id | c1 |
+------+------+
| 10 | 0 |
| 20 | 0 |
| 30 | 0 |
+------+------+
3 rows in set (0.01 sec)
在REPEATABLE READ下,更新一条记录不提交,然后看看能阻塞另外的会话哪些操作。
SESSION 1:
SESSION 1中更新id=20的记录
mysql> begin;
Query OK, 0 rows affected (0.00 sec) mysql> update tb2 set c1=2 where id=20;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0
SESSION 2:
SESSION 2中,执行插入操作,发现[10,30)范围不能插入数据。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into tb2 values(9,4);
Query OK, 1 row affected (0.00 sec) mysql> insert into tb2 values(10,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into tb2 values(19,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into tb2 values(20,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into tb2 values(21,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into tb2 values(29,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into tb2 values(30,4);
Query OK, 1 row affected (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update tb2 set c1=4 where id=10;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0 mysql> update tb2 set c1=4 where id=20;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update tb2 set c1=4 where id=30;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 2 Changed: 0 Warnings: 0
如果SESSION 1的表扫描没有用到索引,那么gap或next-key锁住的范围是整个表,即任何值都不能插入。
2.2 READ COMMITTED
For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE), UPDATE statements,
and DELETE statements, InnoDB locks only index records, not the gaps before them,
and thus permits the free insertion of new records next to locked records.
只会锁住已有记录,不会加gap锁。
2.3 SERIALIZABLE
This level is like REPEATABLE READ, but InnoDB implicitly converts all plain
SELECT statements to SELECT ... LOCK IN SHARE MODE if autocommit is disabled.
和REPEATABLE READ的主要区别在于把普通的SELECT变成SELECT ... LOCK IN SHARE MODE,即对普通的select都会获取gap锁或next-key锁。
4. REPEATABLE READ和幻读
在“consistent-read”时,REPEATABLE READ下看到是事务开始时的快照,即使其它事务插入了新行通常也是看不到的,所以在常见的场合可以避免幻读。 但是,"locking read"或更新,删除时是会看到已提交的修改的,包括新插入的行。
http://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html
If you want to see the “freshest” state of the database, use either the READ COMMITTED
isolation level or a locking read:
下面看一个例子
SESSION 1:
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> select id,c1 from tb1 where id=1;
+----+------+
| id | c1 |
+----+------+
| 1 | 100 |
+----+------+
1 row in set (0.00 sec)
SESSION 2:
mysql> update tb1 set c1=101 where id =1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
SESSION 1:
mysql> select id,c1 from tb1 where id=1 LOCK IN SHARE MODE;
+----+------+
| id | c1 |
+----+------+
| 1 | 101 |
+----+------+
1 row in set (0.00 sec) mysql> select id,c1 from tb1 where id=1;
+----+------+
| id | c1 |
+----+------+
| 1 | 100 |
+----+------+
1 row in set (0.00 sec) mysql> update tb1 set c1=c1+1000 where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select id,c1 from tb1 where id=1;
+----+------+
| id | c1 |
+----+------+
| 1 | 1101 |
+----+------+
1 row in set (0.00 sec)
上面update的行为违反了REPEATABLE READ的承诺,看到了事务开始后其它事务的并发更新。这对应用开发需要特别注意,这种情况下其它数据库通常都是报错的。
5. 其它
RR和RC相比还有一个重要的区别,RC下,扫描过但不匹配的记录不会加锁,或者是先加锁再释放,即semi-consistent read。但RR下扫描过记录都要加锁。这个差别对有全表扫描的更新的场景影响极大。详细参考http://hedengcheng.com/?p=771,关于MySQL的加锁处理,这篇文章讲得很透彻!
6. 参考
- http://hedengcheng.com/?p=771
- http://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html
- http://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html
- http://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html
- http://blog.chinaunix.net/uid-20726500-id-3902528.html
- http://blog.itpub.net/22664653/viewspace-750824/
- http://www.bitscn.com/pdb/mysql/201405/227973.html
转自:http://blog.chinaunix.net/uid-20726500-id-5749804.html
Mysql加锁过程详解(7)-初步理解MySQL的gap锁的更多相关文章
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(2)-关于mysql 幻读理解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(3)-关于mysql 幻读理解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(6)-数据库隔离级别(2)-通过例子理解事务的4种隔离级别
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(1)-基本知识
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(6)-数据库隔离级别(1)
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
随机推荐
- Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
- 可遇不可求的Question之INSERT … ON DUPLICATE KEY UPDATE 语法篇
MySQL 自4.1版以后开始支持INSERT … ON DUPLICATE KEY UPDATE语法,使得原本需要执行3条SQL语句(SELECT,INSERT,UPDATE),缩减为1条语句即可完 ...
- php Glob() 使用 查找文件:
1. 取得所有的后缀为PHP的文件(加上路径)$file=glob('D:/phpStudy/WWW/prictue/*.php');print_r($file);//如果没有指定文件夹的话就是显示出 ...
- Pi的计算
百度百科 圆周率用希腊字母 π(读作pài)表示,是一个常数(约等于3.141592654),是代表圆周长和直径的比值.它是一个无理数,即无限不循环小数.在日常生活中,通常都用3. ...
- 关于Podfile,某个第三方指定源
项目中有个指定了源,摸索好久Podfile编写方式,网上都没有 pod 'SDK名字', :source => '指定源' 其他的直接按原来的就可以了
- docker基础内容讲解
一.初识docker 1.1 LXC介绍 LXC为LinuX Container的简写.Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提 ...
- TCP/IP(一)之开启计算机网络之路
阅读目录(Content) 一.局域网.广域网和Internet 1.1.局域网 1.2.广域网 1.3.Internet 二.计算机数据之间通信的过程 2.1.路由器的功能(转发收到的分组) 三.O ...
- 【java】java反射初探 ——“当类也学会照镜子”
反射的作用 开门见山地说说反射的作用 1.为我们提供了全面的分析类信息的能力 2.动态加载类 我理解的“反射”的意义 (仅个人理解哈) 我理解的java反射机制就是: 提供一套完善而强 ...
- 18年最有"钱"途的专业就是它(文末有福利)
根据社会调查机构麦可思发布的<2018年中国大学生就业报告>中得知,从就业率.薪资和就业满意度等多角度综合考量,信息安全专业为首推绿牌专业. 不管你是计算机相关专业的学生,还是已经工作的I ...
- PHP删除当前目录及其目录下的所有文件
使用PHP遍历一个目录下的所有目录及文件,并删除该目录及其目录下的所有子目录和文件,本次代码通过递归的方式来实现. 用到的函数: scandir($path) 遍历一个目录下所有文件并返回数组. un ...