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. iOS gzip解压

    1. 导入libz库(如:libz 1.2.5.dylib) 2. 引入头文件 #import "zlib.h" 3. 实现解压(输入输出都为NSData对象) -(NSData ...

  2. [leetcode][math] Add Digits

    题目: Given a non-negative integer num, repeatedly add all its digits until the result has only one di ...

  3. HTML5_Web_SQL_Database数据库

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAiEAAAEGCAIAAAA8NNLDAAAgAElEQVR4nOxdd5hcVdk/SUgghCSEhC ...

  4. 基于JS的身份证验证(完整版)

    var Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 ]; // 加权因子 var ValideCode = [ 1, 0 ...

  5. hdu 2018 - 递推

    dp[i][1..4] 第i年时年龄为1234的牛的数目 */ #include <cstdio> #include <cstring> ; ]; int main(){ me ...

  6. exsi主机之间使用scp拷贝文件超时问题

    exsi主机之间使用scp拷贝文件直接连接不上报错超时: 解决: 防火墙勾选ssh选项

  7. NodeJS学习笔记 进阶 (6)本地调试远程服务器上的Node代码(ok)

    https://github.com/chyingp/nodejs-learning-guide

  8. 洛谷1005 【NOIP2007】矩阵取数游戏

    问题描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  9. 第一章、zabbix安装

    前言: 注意:本文不涉及性能测试.性能优化中的监控,所有文字的出发点都是日常运维监控. 在开始之前,我们还是先统一下认识:要监控一个对象,需要掌握哪些东西呢? 监控对象的理解:要监控的对象你是否了解呢 ...

  10. scrapy xpath选择器多级选择错误

    在学习scrapy中用xpath提取网页内容时,有时要先提取出一整个行标签内容,再从行标签里寻找目标内容.出现一个错误. 错误代码: def parse(self, response): sel = ...