InnoDB的锁类型

InnoDB存储引擎支持行锁,锁类型有两种:

  • 共享锁(S锁)
  • 排他锁(X锁)

S和S不互斥,其他均互斥。

除了这两种锁以外,innodb还支持一种锁,叫做意向锁。

那么什么是意向锁?为什么需要意向锁呢?

考虑这种情况:

SessionA:已经持有表t某一行的X锁,需要对行进行更新操作

SessionB:想申请表t的表锁写锁

在没有意向锁之前,SessionA已经持有了行X锁以后,如果SessionB也成功,意味着SessionB可以对这个表中的所有数据进行更新操作,与SessionA的行锁是冲突的。

所以数据库在同意SessionB的申请之前,会做以下的判断:

  1. 检查是否有其他的表级写锁存在
  2. 判断表中每一行是否有行级X锁存在

步骤2的判断本身效率不高。所以产生了意向锁,在申请行级锁之前,先申请意向锁,成功之后才能申请行锁。(简单理解为多保存一个变量,便于申请表锁的时候进行快速判断)。

意向锁分为两种:

  • 意向共享锁(IS锁)
  • 意向排他锁(iX锁)

IS锁和IX锁之间彼此都不互斥,IS和IX只和表级别的读写锁互斥。其中:

  • IX和表X和表S互斥
  • IS和表X互斥
一致性锁定读和一致性非锁定读
一致性非锁定读

当隔离类型设置为读已提交和可重复读时,我们写的普通的select语句,不会申请锁,也不会被阻塞,会从MVCC选择一个视图读取数据。

两种隔离状态的区别在于:

  • 读已提交永远拿到的是最新的视图
  • 可重复读永远使用事务刚建立时拿到的视图
一致性锁定读

当写这两种select语句时,会进行加锁操作。

  • select ... lock in share mode

    • 这个语句表示加入一个S锁,其他事务也可以加S锁
    • 使用场景:不同表之间的相同数据保持一致性时使用(存疑,暂时放着)
  • select ... for update
    • 这个语句表示加入一个X锁,其他事务不能读也不能写
    • 使用场景:先读,根据读结果进行修改的操作时可以使用
行锁的三种算法(判断锁定的范围)

InnoDB存储引擎有三种行锁的锁定算法:

  • record lock:锁定单行
  • gap lock:锁定范围,不包含记录本身
  • next-key lock:gap lock + record lock 既锁定范围又锁定记录本身

当select操作需要加锁时,会按照上面的next-key lock进行加锁。

  • 当查询条件中有索引,并且是唯一索引时,可以只锁定单条记录,由next-key lock降级为 record lock。
  • 当查询条件中有索引,并且索引是辅助索引时,不仅锁住记录本身,还会锁定记录前一个索引键值范围(不包括区间头部的值),除此之外,还会锁定记录值到下一个索引键值的范围(不包括区间尾端的值);同时还会在主键索引的对应行上加record lock
实验验证

输入下列建表语句:

create table z(a int,b int,primary key(a),key(b));
insert into z select 1,1;
insert into z select 3,1;
insert into z select 5,3;
insert into z select 7,6;
insert into z select 10,8;

在sessionA中,输入下面查询语句

select * from z where b=3 for update;

在sessionB中,输入下面查询语句

select * from z where b=1 for update;
select * from z where b=3 for update;
insert into z (a,b) values(4,2);
select * from z where b=6 for update;

其中,第一条和第四条可以正常返回,第二条第三条语句会阻塞,因为SessionA一直没有commit,所以这两条语句阻塞一段时间后会报锁等待超时异常。

mysql> select * from z where b=1 for update;
+---+------+
| a | b |
+---+------+
| 1 | 1 |
| 3 | 1 |
+---+------+
2 rows in set (0.00 sec) mysql> select * from z where b=6 for update;
+---+------+
| a | b |
+---+------+
| 7 | 6 |
+---+------+
1 row in set (0.00 sec) mysql> select * from z where b=3 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into z (a,b) values(4,2);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

结果分析

查询条件为b=3,所以会使用b列的辅助索引来查询,找到记录3后

  • 使用record lock锁定主键索引a=5的记录
  • 使用next-key lock锁定辅助索引(1,3)3 (3,6)这个范围的记录

在SessionA提交事务之前,这个范围内的记录都加的是X排他锁,所以第二条和第三条记录都需要阻塞等待。

MySQL-InnoDB行锁的更多相关文章

  1. Mysql InnoDB行锁实现方式(转)

    Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...

  2. Mysql InnoDB行锁实现方式

    Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...

  3. Mysql InnoDB行锁不使用索引锁表的时候会锁整张表

    原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...

  4. Mysql研磨之InnoDB行锁模式

    事务并发带来的一些问题 (1)更新丢失(LostUpdate):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题最后的更新覆盖了由其 ...

  5. MySQL锁---InnoDB行锁需要注意的细节

    前言 换了工作之后,接近半年没有发博客了(一直加班),emmmm.....今天好不容易有时间,记录下工作中遇到的一些问题,接下来应该重拾知识点了.因为新公司工作中MySQL库经常出现查询慢,锁等待,节 ...

  6. MySQL锁:03.InnoDB行锁

    目录 InnoDB 行锁 锁排查可以用的视图和数据字典 InnoDB 行锁兼容性 InnoDB行锁之共享锁 共享锁: 查看InnoDB锁 InnoDB行锁实现机制 对普通索引上锁 InnoDB隐式.显 ...

  7. mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

    一.概述 Innodb 行锁是通过给索引上的索引项加锁来实现的.这一点与(oracle,sql server)不同后者是通过在数据块中对相应的数据行加锁.这意味着只有通过索引条件检索数据,innodb ...

  8. Innodb行锁源码学习(一)

    Innodb是mysql数据库中目前最流行的存储引擎,innodb相对其它存储引擎一个很大的特点是支持事务,并且支持行粒度的锁.今天我重点跟大家分享下innodb行锁实现的基础知识.由于篇幅比较大,文 ...

  9. 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

    该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...

  10. MySQL InnoDB引擎锁的总结

    为什么要锁 我们开的的各式各样系统中,系统运行需要CPU.内存.I/O.磁盘等等资源.但除了硬资源外,还有最为重要的软资源:数据. 当人们访问操作我们的系统时,其实归根是对数据的查看与生产.那么对于同 ...

随机推荐

  1. salesforce零基础学习(一百四十二)在Formula字段中如何通过Datetime字段显示Local Time(适配DST)

    背景: 我们需求是显示Date Time类型的Time信息,比如我们想要在report中基于Hour Of Created Date进行分组,从而想要了解到一段时间内什么时间是数据创建的高峰期,不同的 ...

  2. C# WinForm 托盘程序

    实现步骤 创建 NotifyIcon 控件并设置属性: 编写 NotifyIcon 响应控制事件: 在主窗体的Load事件中将 NotifyIcon 添加到系统托盘: 程序退出时,移除系统托盘的 No ...

  3. .NET 开发的分流抢票软件,不做广告、不收集隐私

    前言 每年春节大家必备的抢票工具Bypass-分流抢票.分流抢票是一款免费无广适用于PC端的自动分流抢票软件. 分流抢票,是以用户为中心.人性化的抢票软件.不做广告.不做推广.不携带病毒.不收集隐私信 ...

  4. WPF中webview2鼠标移动窗体

    WPF里webview2会一直处于其他控件最上层,是个历史遗留问题. 为了能在webview2里鼠标移动让窗体跟着移动位置代码如下: async Task InitializeAsync() { Ap ...

  5. Linux 常用脚本命令-lsof、find、rpm、SS、top、vim

    1,关机命令 1 shutdown -h now/0 2 halt 3 init 0 4 poweroff 5 举例: 6 shutdown -h 3 ------3分钟后关机(可用shutdown ...

  6. Golang-容器3

    http://c.biancheng.net/golang/container/ Go语言数组详解 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.因为数组的长度是固定 ...

  7. JVM虚拟机---常用JVM配置参数

    常用JVM配置参数 常用JVM配置参数主要有:Trace跟踪参数.堆的分配参数.栈的分配参数. 一.Trace跟踪参数 跟踪参数用于跟踪监控JVM,对于开发人员来讲用于JVM调优以及故障排查的. 1. ...

  8. C:.c文件和.h文件的关系

    参考:1      2 问题 在进行C语言文件移植时,遇到 "通常是每个.c文件对应一个.h文件",之前了解过.h文件是头文件,用来引用其他文件的, 但在codeblocks C语 ...

  9. Django环境的Linux安装(使用put方法将本地安装包导入到Linux)

    1.建立Sftp链接 2.使用put命令将本地的安装包拉取到指定目录. 3.使用tar xzvf 命令将安装包解压到创建好的目录. 4.cd Django-* 5.执行安装命令:sudo python ...

  10. 男人八题-点分治-Acwing252.树

    Acwing252.树 题目分析 树中的路径分为三种 路径两端在同一个子树 路径两端在不同子树 路径有一端是重心 因此可以分情况处理, 对于第一种情况可以进行递归处理, 第二种情况需要使用容斥原理求得 ...