Innodb锁的类型

行锁(record lock)

行锁总是对索引上锁,如果某个表没有定义索引,mysql就会使用默认创建的聚集索引,行锁有S锁和X锁两种类型。

共享锁和排它锁

Innodb锁有两种类型:共享锁(S lock)和排它锁(X lock)

  • 不同事务可以同时对同一行记录加S锁
  • 如果一个事务对某一行记录加X锁,其他事务就不能加S锁或者X锁,从而导致锁等待

使用sqlSELECT ... LOCK IN SHARE MODE可以对一行记录加S锁,sql SELECT ... FOR UPDATE则是加X锁

意向锁(intention lock)

Innodb为了支持多粒度的加锁,允许行锁和表锁同时存在。插入意向锁即是一种表锁,在事务对某一行或者多行加锁之前,必须对这张表加入意向锁(或更强的锁如X锁)。插入意向锁分为:

  • intention shared lock (IS):表明事务对于这张表的记录有插入S锁的意向
  • intention exclusive lock (IX):表明事务对于这张表的记录有插入X锁的意向

插入意向锁和其他表锁兼容性如下:

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

对表加S锁或者X锁可以参考:https://dev.mysql.com/doc/refman/5.7/en/lock-tables.html

间隙锁(gap lock)

间隙锁锁住一个间隙以防止插入。假设索引列有(a,b,c)三个值,如果对b加锁,那么也会同时对(a,b)和(b,c)这两个间隙加锁。其他事务无法插入索引值在这两个间隙之间的记录(即a<索引值<b或者b<索引值<c都无法插入)。但是,间隙锁有一个例外:

  • 如果索引列是唯一索引,那么只会锁住这条记录(只加行锁),而不会锁住间隙。
  • 对于联合索引且是唯一索引,如果where条件只包括联合索引的一部分,那么依然会加间隙锁。

对于间隙锁来说,S锁或者X锁没有区别,它们也不会相互冲突。假设索引列有(a,b,c,d)四个值,事务A对b加X锁,也会同时对(a,b)和(b,c)这两个间隙加X锁。其他事务B可以同时对c加X锁,也会同时对(b,c)和(c,d)这两个间隙加X锁。可以看到两个事务都可以对(b,c)这个间隙加X锁,但是不会引起冲突。

注意,如果将数据库隔离级别改为READ COMMITTED或者开启系统变量innodb_locks_unsafe_for_binlog,那么间隙锁就会被关闭。

next-key lock

next-key lock实际上就是行锁+这条记录前面的gap lock的统称。假设有索引值10, 11, 13, 和20,那么可能的next-key lock包括:

(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

在REPEATABLE READ隔离级别下,InnoDB使用next-key lock主要是防止幻像问题(phantom problem)的产生。

幻想问题指的是一个事务中,两次执行同一个sql可能返回不同数据的现象。这违反了事务的隔离性。设表t有1,2,5三个值。事务A执行以下sql

select * from t where a>2 for update

如果事务没有提交,在没有next-key lock的情况下其他事务B又插入了4这个值并提交,那么A事务再次执行上面的sql就会返回a=4这个值。

插入意向锁(Insert Intention Lock)

插入意向锁指的是事务在对一个gap插入之前会对这个gap加插入意向锁。只要不同事务对于同一个gap插入的位置不同,那么就可以对同一个gap同时加插入意向锁。设有某列有索引值2,6,只要两个事务插入位置不同(如事务A插入3,事务B插入4),那么就可以同时插入。

自增锁(AUTO-INC Lock)

自增锁是一种特殊的表锁。一般说来,为了实现列的自增,不同事务对自增列的插入都会导致锁等待。不过后面mysql对于自增锁做了大量优化,提供了不同算法以实现性能和数据一致的平衡。具体可以参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html

Innodb加锁分析

详细参考:mysql InnoDB加锁分析

Innodb锁等待排查

目前Innodb提供的锁等待排查命令有下面几个:

SHOW FULL PROCESSLIST ;
SHOW ENGINE INNODB STATUS ;
#更为详细
select * from information_schema.INNODB_TRX;
select * from information_schema.INNODB_LOCKS;
select * from information_schema.INNODB_LOCK_WAITS;

通常我使用如下sql来获取必要的信息:

select l.*, t.trx_state,t.trx_weight,t.trx_query,w.* from information_schema.INNODB_TRX t left join information_schema.INNODB_LOCKS l
on t.trx_id=l.lock_trx_id left join information_schema.INNODB_LOCK_WAITS w
on t.trx_id=w.requesting_trx_id;

排查方式可以参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-examples.html

Innodb一致性非锁定读(consistent nonblocking read)

前面一个章节讲的是锁定读以保证更新插入数据的一致性,mysql同时也提供不加锁的方式读取数据。mysql使用多版本并发控制(MVCC)来读取数据,如果事务A对某一行正在执行update或delete操作,那么事务B不会读取正在更新的这一行,而是会去读取这行的一个快照数据。



该实现是通过undo段完成,因为undo段用来事务的回滚,因此本身没有额外的开销。

不同的事务隔离级别下,读取的快照版本也不相同

  • READ COMMITTED级别下,一致性非锁定读总是读取被锁定行的最新一份快照数据。所以在这个隔离级别下,同一个事务多次读取同一条记录,返回的结果可能不同,因为存在其他事务提交对这一行更新的可能。
  • REPEATABLE READ级别下,一致性非锁定读总是读取被锁定行事物开始时的行数据版本。同一个事务多次读取同一条记录返回相同的结果。

Innodb锁的类型的更多相关文章

  1. InnoDB 锁的类型

    一.全局锁 mysql> flush table with read lock; FTWRL 会对整个实例加只读锁.会阻塞所有线程读以外的所有操作.查看线程状态 State: Waiting f ...

  2. innodb 锁分裂继承与迁移

    innodb行锁简介 行锁类型 LOCK_S:共享锁 LOCK_X: 排他锁 GAP类型 LOCK_GAP:只锁间隙 LOCK_REC_NO_GAP:只锁记录 LOCK_ORDINARY: 锁记录和记 ...

  3. InnoDB锁机制分析

    InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工作机制.通过 ...

  4. Innodb锁机制:Next-Key Lock 浅谈

    数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性.InnoDB是一个支持行锁的存储引擎,锁的类型有:共享锁(S).排他锁(X).意向共享(IS).意向排他(IX).为了提供更好的并发,Inn ...

  5. [转载] 数据库分析手记 —— InnoDB锁机制分析

    作者:倪煜 InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工 ...

  6. Innodb锁机制:Next-Key Lock 浅谈(转)

    http://www.cnblogs.com/zhoujinyi/p/3435982.html 数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性.InnoDB是一个支持行锁的存储引擎,锁的类 ...

  7. MySQL · 特性分析 · innodb 锁分裂继承与迁移

    http://mysql.taobao.org/monthly/2016/06/01/ innodb行锁简介 行锁类型 LOCK_S:共享锁 LOCK_X: 排他锁 GAP类型 LOCK_GAP:只锁 ...

  8. Innodb 锁系列2 事务锁

    上一篇介绍了Innodb的同步机制锁:Innodb锁系列1 这一篇介绍一下Innodb的事务锁,只所以称为事务锁,是因为Innodb为实现事务的ACID特性,而添加的表锁或者行级锁. 这一部分分两篇来 ...

  9. MySQL- InnoDB锁机制

    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...

随机推荐

  1. 局部加权回归、欠拟合、过拟合 - Andrew Ng机器学习公开课笔记1.3

    本文主要解说局部加权(线性)回归.在解说局部加权线性回归之前,先解说两个概念:欠拟合.过拟合.由此引出局部加权线性回归算法. 欠拟合.过拟合 例如以下图中三个拟合模型.第一个是一个线性模型.对训练数据 ...

  2. 零基础学python-6.2 共享引用

    这一章节说说共享引用 我们先举一个样例 a=1 b=a 上面的样例就是共享引用,这里我们说说整个过程: 1.创建一个对象1 2.创建一个变量a 3.把a和1所在的内存空间连接起来.就是a引用1 4.a ...

  3. css中使用id和class 的不同

    在 CSS 中,类选择器以一个点号显示: .center {text-align: center} 在上面的样例中,全部拥有 center 类的 HTML 元素均为居中. 在以下的 HTML 代码中, ...

  4. iOS自动布局高级用法 && 纯代码约束写法

    本文主要介绍几个我遇到的总结的高级用法(当然我相信肯定有不少比这还高级的). 简单的storyboard中上下左右约束,固定宽高啥的用法在这里就不做赘述了. autolayout自动布局是iOS6以后 ...

  5. 求解n位格雷码

    /************************************************************************* > File Name: Gray.cpp ...

  6. Random words

    To choose a random word from the histogram, the simplest algorithm is to build a list with multiple ...

  7. Angular2/Ionic2集成Promact/md2.md

    最近想找一套比较完整的基于Material风格的Angular2的控件库,有两个选择一个是Angular官方的Material2,但是这套库的DatePicker控件目前只能支持年月日,不支持时分秒, ...

  8. 51Nod 最长的循环节(打表预处理)

    正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求<=n的数中,倒数循环节长度最长的那个数,假如存在多个最优的答案,输出所有答案中最大的那个数.     1/6= ...

  9. python shutil 模块 的剪切文件函数 shutil.movemove(src, dst),换用 os.rename(sourceFile, targetFile)

    Google 一搜python 剪切文件,出来shutil 这模块,网上很多人也跟疯说shutil.move(src, dst)就是用来剪切文件的,结果一试,剪切毛线,文件都复制到另一个文件夹了,源文 ...

  10. FragmentActivity+FragmentTabHost+Fragement替代TabActibvity+TabHost+Activity

    自Android3.2之后,TabActibvity被弃用(Deprecated).取而代之的是FragmentActivity.由于Fragment比Activiy更灵活.消耗的资源更小.全然可以满 ...