• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >Mysql > MySQL数据库InnoDB引擎行级锁锁定范围详解

MySQL数据库InnoDB引擎行级锁锁定范围详解

作者:匿名 字体:[增加 减小] 来源:互联网 时间:2018-12-05

匿名通过本文主要向大家介绍了InnoDB,MySQL,数据库等相关知识,希望本文的分享对您有所帮助
Mysql数据库InnoDB引擎支持行级锁,也就是说我们可以对表中某些行数据执行锁定操作,锁定操作的影响是:如果一个事物对表中某行执行了锁定操作,而另一个事务也需要对同样的行执行锁定操作,这样第二个事务的锁定操作有可能被阻塞,一旦被阻塞第二个事务只能等到第一个事务执行完毕(提交或回滚)或超时。

本文主要介绍InnoDB中的行锁相关概念,重点介绍行锁的锁定范围:

  • 什么样的SQL语句会加锁?

  • 加什么样的锁?

  • 加锁语句会锁定哪些行?

背景知识

上面我们简单的介绍了InnoDB的行级锁,为了理解后面的验证部分,需要补充一下背景知识。如果对相应知识非常了解,可以直接跳转到验证部分内容。

1. InnoDB锁的类型

InnoDB引擎使用了七种类型的锁,他们分别是:

  • 共享排他锁(Shared and Exclusive Locks)

  • 意向锁(Intention Locks)

  • 记录锁(Record Locks)

  • 间隙锁(Gap Locks)

  • Next-Key Locks

  • 插入意图锁(Insert Intention Locks)

  • 自增锁(AUTO-INC Locks)

本文主要涉及Shared and Exclusive Locks,Record Locks,Gap Locks,Next-Key Locks这几种锁,其他类型锁如果大家感兴趣可以自己深入了解,在此不在详述。

1.1 Shared and Exclusive Locks

共享锁(S锁)和排他锁(X锁)的概念在许多编程语言中都出现过。先来描述一下这两种锁在MySQL中的影响结果:

  • 如果一个事务对某一行数据加了S锁,另一个事务还可以对相应的行加S锁,但是不能对相应的行加X锁。

  • 如果一个事务对某一行数据加了X锁,另一个事务既不能对相应的行加S锁也不能加X锁。

用一张经典的矩阵表格继续说明共享锁和排他锁的互斥关系:

--SX
S01
X11

图中S表示共享锁X表示独占锁,0表示锁兼容1表示锁冲突,兼容不被阻塞,冲突被阻塞。由表可知一旦一个事务加了排他锁,其他个事务加任何锁都需要等待。多个共享锁不会相互阻塞。

1.2 Record Locks、Gap Locks、Next-Key Locks

这三种类型的锁都描述了锁定的范围,故放在一起说明。

以下定义摘自MySQL官方文档

  • 记录锁(Record Locks):记录锁锁定索引中一条记录。

  • 间隙锁(Gap Locks):间隙锁要么锁住索引记录中间的值,要么锁住第一个索引记录前面的值或者最后一个索引记录后面的值。

  • Next-Key Locks:Next-Key锁是索引记录上的记录锁和在索引记录之前的间隙锁的组合。

定义中都提到了索引记录(index record)。为什么?行锁和索引有什么关系呢?其实,InnoDB是通过搜索或者扫描表中索引来完成加锁操作,InnoDB会为他遇到的每一个索引数据加上共享锁或排他锁。所以我们可以称行级锁(row-level locks)为索引记录锁(index-record locks),因为行级锁是添加到行对应的索引上的。

三种类型锁的锁定范围不同,且逐渐扩大。我们来举一个例子来简要说明各种锁的锁定范围,假设表t中索引列有3、5、8、9四个数字值,根据官方文档的确定三种锁的锁定范围如下:

  • 记录锁的锁定范围是单独的索引记录,就是3、5、8、9这四行数据。

  • 间隙锁的锁定为行中间隙,用集合表示为(-∞,3)、(3,5)、(5,8)、(8,9)、(9,+∞)。

  • Next-Key锁是有索引记录锁加上索引记录锁之前的间隙锁组合而成,用集合的方式表示为(-∞,3]、(3,5]、(5,8]、(8,9]、(9,+∞)。

最后对于间隙锁还需要补充三点:

  1. 间隙锁阻止其他事务对间隙数据的并发插入,这样可有有效的解决幻读问题(Phantom Problem)。正因为如此,并不是所有事务隔离级别都使用间隙锁,MySQL InnoDB引擎只有在Repeatable Read(默认)隔离级别才使用间隙锁。

  2. 间隙锁的作用只是用来阻止其他事务在间隙中插入数据,他不会阻止其他事务拥有同样的的间隙锁。这就意味着,除了insert语句,允许其他SQL语句可以对同样的行加间隙锁而不会被阻塞。

  3. 对于唯一索引的加锁行为,间隙锁就会失效,此时只有记录锁起作用。

2. 加锁语句

前面我们已经介绍了InnoDB的是在SQL语句的执行过程中通过扫描索引记录的方式来实现加锁行为的。那哪些些语句会加锁?加什么样的锁?接下来我们逐一描述:

  • select ... from语句:InnoDB引擎采用多版本并发控制(MVCC)的方式实现了非阻塞读,所以对于普通的select读语句,InnoDB并不会加锁【注1】。

  • select ... from lock in share mode语句:这条语句和普通select语句的区别就是后面加了lock in share mode,通过字面意思我们可以猜到这是一条加锁的读语句,并且锁类型为共享锁(读锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描的唯一索引的唯一行,next-key降级为索引记录锁。

  • select ... from for update语句:和上面的语句一样,这条语句加的是排他锁(写锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。

  • update ... where ...语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。【注2】

  • delete ... where ...语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。

  • insert语句:InnoDB只会在将要插入的那一行上设置一个排他的索引记录锁。

最后补充两点:

  1. 如果一个查询使用了辅助索引并且在索引记录加上了排他锁,InnoDB会在相对应的聚合索引记录上加锁。

  2. 如果你的SQL语句无法使用索引,这样MySQL必须扫描整个表以处理该语句,导致的结果就是表的每一行都会被锁定,并且阻止其他用户对该表的所有插入。

SQL语句验证

闲言少叙,接下来我们进入本文重点SQL语句验证部分。

1.测试环境

数据库:MySQL 5.6.35
事务隔离级别:Repeatable read
数据库访问终端:mysql client

2.验证场景

2.1 场景一

建表:

CREATE TABLE `user` (
 `id` int(11) NOT NULL,
 `name` varchar(8) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据:

INSERT INTO `user` (`id`, `name`) VALUES ('1', 'a');
INSERT INTO `user` (`id`, `name`) VALUES ('3', 'c');
INSERT INTO `user` (`id`, `name`) VALUES ('5', 'e');
INSERT INTO `user` (`id`, `name`) VALUES ('7', 'g');
INSERT INTO `user` (`id`, `name`) VALUES ('9', 'i');

首先我们执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' for update;--
3--begin;
4--INSERT INTO `user` (`id`, `name`) VALUES (10, #{name});
5rollback;--
6--rollback;

替换步骤5中name的值,观察结果:

name的值执行结果
a不阻塞
b不阻塞
d阻塞
e阻塞
f阻塞
h不阻塞
i不阻塞

观察结果,我们发现SQL语句
SELECT * FROM user where name='e' for update
一共锁住索引name中三行记录,(c,e]区间应该是next-key锁而(e,h)区间是索引记录e后面的间隙。

接下来我们确定next-key锁中哪部分是索引记录锁哪部分是间隙锁。

执行SQL语句的模板:

步骤client 1client 2
1begin;--
2SELECT * FROM user where name='e' f
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 探讨:innodb与myisam在存储上有何特点和区别
  • 深入MySQL存储引擎比较的详解
  • 浅谈MySQL存储引擎选择 InnoDB与MyISAM的优缺点分析
  • 深入探讨:MySQL数据库MyISAM与InnoDB存储引擎的比较
  • 关于mysql中innodb的count优化问题分享
  • MySQL Innodb表导致死锁日志情况分析与归纳
  • 关于mysql innodb count(*)速度慢的解决办法
  • InnoDB引擎数据库主从复制同步新的分享
  • show engine innodb status显示信息不全如何解决
  • MyISAM和InnoDB引擎优化分析

相关文章

  • 2018-12-05MySQL多实例的配置和管理详细
  • 2018-12-05MySQL之—新安装的MySQL必须调整的10项配置的详细介绍
  • 2018-12-05什么是blob,mysql blob大小配置介绍
  • 2017-05-11MySQL5.1主从同步出现Relay log read failure错误解决方法
  • 2017-05-11与MSSQL对比学习MYSQL的心得(七)--查询
  • 2017-05-11MySQL查询倒数第二条记录实现方法
  • 2018-12-05oracle的rownum深入解析
  • 2018-12-05使用mysqli扩展技术实现多个数据表查询
  • 2018-12-05MySQL存储过程 游标 错误处理的示例代码
  • 2017-05-11MySQL 文本文件的导入导出数据的方法

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • SqlServer2005 自动备份并存储另一电脑上的存储过程函数
    • Mysql5.7.19在Centos7下安装教程详解
    • MySQL性能优化 出题业务SQL优化
    • MYSQL 修改root密码命令小结
    • 有关表的信息的10篇文章推荐
    • Mysql报错:1130-host ... is not allowed to connect to this MySql server如何处理
    • 关于mysql exists与not exists分析
    • fetch()怎么使用?pdo中fetch()用法实例总结
    • 在CentOS上MySQL数据库服务器配置方法
    • RavenDB在传统C/S应用下的一点实践

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有