测试环境隔离级别:REPEATABLE-READ

行级别的 - Share and Exclusive Locks

  • 共享锁 S:允许持有S锁的事务对行进行读操作
  • 排他锁 X: 允许持有X锁的事务对行进行update或delete操作

表级别的意向锁 - Intention Lock

InnoDB支持多粒度的锁定,允许行锁和表锁共存。通过意向锁来实现。

比如,SELECT ... LOCK IN SHARE MODE sets an IS lock and SELECT ... FOR UPDATE sets an IX lock.

  • 意向共享锁(IS):在对数据行获取S锁之前,必须先获取IS锁或更强级别的锁
  • 意向排他锁(IX):在对数据行获取X锁之前,必须先获取IX锁

不同类型锁之间的兼容总结

  X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

A lock is granted to a requesting transaction if it is compatible with existing locks, but not if it conflicts with existing locks.

A transaction waits until the conflicting existing lock is released. If a lock request conflicts with an existing lock and cannotbe granted because it would cause deadlock, an error occurs.

因此,除了对整个表的请求(比如,LOCK TABLES ... WRITE)外,意向锁不会阻塞其他的事务。持有意向锁表示持有者正在锁定数据行,或者即将锁定数据行。

deadlock:

A deadlock can occur when the transactions lock rows in multiple tables (through statements such as UPDATE or SELECT ... FOR UPDATE), but in the opposite order. A deadlock can also occur when such statements lock ranges of index records and gaps, with each transaction acquiring some locks but not others due to a timing issue.

索引记录上的锁 - Record Lock

比如,SELECT c1 FOR UPDATE FROM t WHERE c1 = 10;避免其他的事务在t.c1=10的位置进行insert、update和delete操作

record lock始终锁定索引记录,即使一个表没有进行索引定义,对于这种情况,InnoDB创建一个隐藏的聚集索引并使用该索引记录锁定

Cap Lock

比如,SELECT c1 FOR UPDATE FROM t WHERE c1 BETWEEN 10 and 20;会在t.c1在10到20之间的索引记录上加锁,防止其他的事务在t.c1列上插入10到20之间的值

测试:t2.id上无索引

mysql> select * from t2;                         
+------+                                
| id   |                                
+------+                                
|    1 |                                
|    5 |                                
|    8 |                                
|   11 |                                
+------+                                
4 rows in set (0.00 sec)                
                                        
S1                                                                     S2    
mysql> begin;                           
Query OK, 0 rows affected (0.00 sec)    
                                                                        mysql> begin;                                                             
mysql> update t2 set id=6 where id=5;                Query OK, 0 rows affected (0.00 sec)                                      
Query OK, 1 row affected (0.00 sec)                                                                               
Rows matched: 1  Changed: 1  Warnings: 0           mysql> insert into t2 values(5);                                          
                                                                         ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
                                                                         mysql> insert into t2 values(1);                                          
                                                                         ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
                                                                         mysql> insert into t2 values(8);                                          
                                                                         ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
                                                                         mysql> insert into t2 values(6);  
                                                                         ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

S1锁住整张表

t2.id上加上索引的验证

mysql> alter table t2 add index id_idx(id);    
Query OK, 0 rows affected (0.54 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
                                                                              mysql> begin;                                                                
mysql> update t2 set id=6 where id=5;                      Query OK, 0 rows affected (0.00 sec)                                                                        
Query OK, 1 row affected (0.00 sec)                                                                                                     
Rows matched: 1  Changed: 1  Warnings: 0                mysql> insert into t2 values(8);                                                                                                            
                                                                              Query OK, 1 row affected (0.00 sec)                                          
                                                                                                                                        
                                                                              mysql> insert into t2 values(7);                                             
                                                                              ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction   
                                                                              mysql> insert into t2 values(1);                                             
                                                                              ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction   
 S1会在[1,5] [5,8)区间加上间隙锁

Next-Key Locks

A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record.

InnoDB uses next-key locks for searches and index scans, which prevents phantom rows .

幻影读的解释:http://dev.mysql.com/doc/refman/5.6/en/innodb-next-key-locking.html

验证如上:S1会在id=5的行加上X锁,为防止幻读,又在5的左边[1,5) 和5的又边(5,8)加上了gap锁

Insert Intention Locks

是gap锁的一种。多个事务如果不是在相同的索引范围内插入,则无需等待彼此

测试:

mysql> select * from t2;
+------+
| id   |
+------+
|    1 |
|    5 |
|    8 |
|   11 |
+------+

会话S1                                                         会话S2
mysql> begin;                                                                          
Query OK, 0 rows affected (0.00 sec)                                                   
                                                                                                                                                               
mysql> insert into t2(id) values(7);                 mysql> begin;                                                   
Query OK, 1 row affected (0.00 sec)               Query OK, 0 rows affected (0.00 sec)

mysql> insert into t2(id) values(6);
                                                                   Query OK, 1 row affected (0.00 sec)

mysql> insert into t2(id) values(7);
                                                                   Query OK, 1 row affected (0.00 sec)

两个会话在插入的行上获取排他锁前,分别在id为5~8的行记录范围内持有intention locks,但不会阻塞对方,因为行之间没有冲突。

再举一个会话在要插入的行记录上获取排他锁之前获取insert intention lock但被阻塞的例子:

S1在id>5的行持有排它锁。此排它锁包含5~11之间的gap锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2 where id>5 for update;
+------+
| id   |
+------+
|    8 |
|   11 |
+------+

S2上在S1查询出的行范围内插入行记录。会持有insert intention lock,但是会等待排它锁

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t2 values(7);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

参考链接:

http://dev.mysql.com/doc/refman/5.6/en/innodb-locking.html

http://www.hollischuang.com/archives/923

InnoDB 存储引擎的锁机制的更多相关文章

  1. InnoDB存储引擎的锁

    InnoDB存储引擎的锁 锁的类型 锁的类型包括: 1.     共享锁(S lock),允许事务读取一行数据 2.     排他锁(X lock),允许事务删除或更新一行数据 锁的兼容性a X S ...

  2. 图文实例解析,InnoDB 存储引擎中行锁的三种算法

    前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁.具体来说,InnoDB 采用的是两阶段锁定协议(tw ...

  3. Mysql存储引擎以及锁机制

    一.常用命令 1.查看引擎(默认为InnoDB) 查看mysql提供的存储引擎:show engienes 查看mysql当前默认的存储引擎:show variables like '%storage ...

  4. 《Mysql技术内幕,Innodb存储引擎》——锁

    lock与latch 在数据库中lock与latch分别指不同的所. latch:可分为互斥量(mutex)和读写锁(rwlock),目的在于保证数据库内部的结构中共享资源并发时能够正确操作,其对象主 ...

  5. Galera集群server.cnf参数调整--Innodb存储引擎内存相关参数(一)

    在innodb引擎中,内存的组成主要有三部分:缓冲池(buffer pool),重做日志缓存(redo log buffer),额外的内存池(additional memory pool).

  6. MySQL内核:InnoDB存储引擎 卷1

    MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...

  7. 1009MySQL数据库InnoDB存储引擎Log漫游

    00 – Undo Log Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atom ...

  8. MySQL InnoDB存储引擎undo redo解析

    本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...

  9. InnoDB存储引擎介绍-(2)redo和undo学习

    01 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...

随机推荐

  1. PBOC金融IC卡,卡片与终端交互的13个步骤,简介-第三组

    七:终端风险管理-必选但包含可选步骤异常文件:终端检查应用主账号是否在异常文件列表(卡号黑名单)中.商户强制联机:商户可以将当前交易强制为联机处理.最低限额:控制交易当前交易金额或同一张卡片连续几笔交 ...

  2. Redis在JAVA中的运用(工具类)

    最近项目需要用redis在中间做缓存所以写了一个工具类作为练习用 redis版本:redis_version:3.0.504 用到阿里的解析JSON的库:fastjson import org.apa ...

  3. 在linux上部署web环境

    1.升级python到2.7版本(通过源码包重新安装一个2.7版本的python):wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9. ...

  4. d3 scale 学习笔记

    讲解scale 的好材料 https://www.dashingd3js.com/d3js-scales

  5. 【Javascript】重新绑定默认事件

    更多内容,请移步 JSCON-简时空 在有一种场景下,你想先屏蔽掉默认的系统事件,而在特定条件下又重新绑定回去. [场景]H5页面,动画欢迎界面,共6帧:想在前5帧中屏蔽掉默认的touchmove事件 ...

  6. js动态替换数据的点击事件

    做项目时遇到的,具体是界面如下图:当点击X号时,出现删除.取消按钮,当点击删除时,这一行删除,当点击取消时又恢复到初始状态. 需要关注的问题是,js动态添加的删除.取消按钮的点击事件.当点击取消时恢复 ...

  7. 如何用php生成1-10之间的不重复随机数

       今天跟大家分享一个PHP中的案列,大家一起学习学习.                                                        使用shuffle函数生成随机 ...

  8. Redis常用命令入门4:集合类型

    集合类型 之前我们已经介绍过了最基本的字符串类型.散列类型.列表类型,下面我们一起学习一下集合类型. 集合类型也是体现redis一个比较高价值的一个类型了.因为Redis的集合类型,所以我们可以很容易 ...

  9. SQL Server数据库脚本备份与还原

    use[master]go /*完整--备份* backup 备份 * disk='E:\USERDB.bak' 磁盘,备份文件存放的路径* name='user' 备份显示的文件名称,可随意修改* ...

  10. 一个网络传输框架——zeroMQ 调研笔记

    一.它是什么 zeroMQ,一个处理消息传输的库,重点在传输上,看起来它像是在socket上面封装了一层,让我们可以很容易的利用它来做N对M的数据传输,在分布式系统中很方便,在接收端它有round-r ...