mysql中InnoDB事务隔离的记录锁、间隙锁和临键锁

 更新时间:2023年12月02日 15:11:57   作者:Hello-Brand  
mysql中InnoDB默认的事务隔离级别为可重复读(Repeated Read, RR),我们当下的所有介绍都是基于这个隔离级别为前提的,记录锁锁定索引关联的具体记录,间隙锁锁定间隔,防止间隔中被其他事务插入,临键锁锁定索引记录+间隔,防止幻读

InnoDB默认的事务隔离级别为可重复读(Repeated Read, RR),我们当下的所有介绍都是基于这个隔离级别为前提的。

  • 记录锁(Record Locks):锁定单一行记录,InnoDB 使用记录锁来实现行级锁,这样允许多个事务并发访问不同的行。
  • 间隙锁(Gap Locks):InnoDB 的特性,用于锁定一个范围,但不包括实际的记录。这主要用于防止幻读(Phantom Reads)。
  • 临键锁(Next-Key Locks):InnoDB 存储引擎的一种锁定机制,在执行查询语句时,根据查询条件所锁定的一个范围。这个范围中包含有间隙锁和记录锁。它的设计目的是为了解决幻读(Phantom Reads)。

记录锁(Record Locks)

记录锁,它封锁索引记录,例如:

select * from table where id=5 for update;

它会在id=1的索引记录上加锁,以阻止其他事务插入,更新,删除id=1的这一行。

需要说明的是:

select * from table where id=5;

则是快照读(SnapShot Read),它并不加锁,快照读可以参考作者这篇文章:数据库系列:RR和RC下,快照读的区别

间隙锁(Gap Locks)

间隙锁,它封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
延续上面的那个例子继续演示:

# 表结构
table (Id PK, Name , Company);
# 表中包含四条记录
5, Gates, Microsoft
7, Bezos, Amazon
11, Jobs, Apple
14, Elison, Oracle

执行SQL语句如下:

select * from table
    where id between 7 and 13 
    for update;

这样的话,会封锁数据的区间,以防止其他事务插入id=8的记录。
假设没有间隙锁,则可能够插入成功,而之前的select事务,会发现检索的结果集莫名多了一条记录,即幻影数据。
所以间隙锁主要目的用于防止幻读(Phantom Reads),避免其他事务在间隔中插入数据,导致 『不可重复读』。
如果把事务的隔离级别降级为读提交(Read Committed, RC),对,就是互联网最常用的隔离级别,间隙锁则会自动失效。

临键锁(Next-Key Locks)

临键锁(Next-Key Locks)是数据库管理系统InnoDB中的一种重要锁定机制。这种锁是查询时根据查询条件锁定的一个范围,这个范围包括间隙锁和记录锁,左开右闭,即不锁住左边界,但会锁住右边界。临键锁的主要设计目的是为了解决所谓的“幻读”问题。

# 左开右闭 示例
(-infinity, 1]
(1, 7]
(7, 9]
(9, +infinity]

依然沿用上面的例子,InnoDB引擎,RR隔离级别:

-- 创建一个示例表  
CREATE TABLE users (  
    Id INT PRIMARY KEY,  
    Name VARCHAR(255) NOT NULL,  
    Company VARCHAR(255) NOT NULL,  
);  
  
-- 插入一些示例数据  
INSERT INTO users (id, name, company) VALUES (1, 'Alice', 'ali');
INSERT INTO users (id, name, company) VALUES (2, 'Brand', 'tencent');
INSERT INTO users (id, name, company) VALUES (3, 'Charlie', 'baidu');
  
-- 开始一个事务,并使用临键锁查询数据  
START TRANSACTION;  
SELECT * FROM users WHERE id > 1 FOR UPDATE;  
  
-- 在另一个事务中尝试插入新数据,将会被阻塞直到第一个事务释放锁 
START TRANSACTION;  
INSERT INTO users (id, name, age) VALUES (4, 'David', 30);  
COMMIT;  
  
-- 第一个事务提交后,第二个事务可以继续执行插入操作  
COMMIT;

临键锁的主要目的,也是为了避免幻读(Phantom Read),在事务隔离级别为可重复读的情况下,InnoDB存储引擎默认使用临键锁。这种锁提供了一种有效的机制来保证在并发环境中数据的完整性和一致性。
如果把事务的隔离级别降级为RC,临键锁则也会失效。

总结

  • InnoDB的索引与行记录存储在一起,MyISAM则是通过索引的地址查找到对应的数据记录,效率低一些
  • InnoDB的聚集索引存储行记录,普通索引存储PK,所以普通索引要查询两次
  • 记录锁锁定索引关联的具体记录
  • 间隙锁锁定间隔,防止间隔中被其他事务插入
  • 临键锁锁定索引记录+间隔,防止幻读
  • select...for update加锁的几种情况:
    • 主键字段:加行锁。
    • 唯一索引字段:加行锁。
    • 普通索引字段:加行锁。
    • 主键范围:加多个行锁。
    • 普通字段:加表锁。
    • 查询空数据:不加锁。
  • 行锁与表锁的区别
    • 如果事务1加了行锁,一直未释放锁,事务2操作相同记录,会一直等待直至超时。
    • 如果事务1加了表锁,一直未释放锁,事务2无论操作哪一行记录,都会一直等待直到超时

到此这篇关于mysql中InnoDB事务隔离的记录锁、间隙锁和临键锁的文章就介绍到这了,更多相关InnoDB的记录锁、间隙锁和临键锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解析mysql中max_connections与max_user_connections的区别

    解析mysql中max_connections与max_user_connections的区别

    本篇文章是对mysql中max_connections与max_user_connections的区别进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • mysql中将null值转换为0的语句

    mysql中将null值转换为0的语句

    mysql中将null值转换为0的语句,在mysql数据库开发中,如果后期添加了字段那么这些值为空值null,我们在使用者需要将null转换为0方便后期的控制就需要下面的代码了。
    2011-02-02
  • Linux系统每日定时备份mysql数据的方法步骤

    Linux系统每日定时备份mysql数据的方法步骤

    这篇文章主要介绍了Linux系统每日定时备份mysql数据的方法步骤,包括创建文件夹、编写脚本、设置定时任务和测试脚本,详细步骤涵盖从文件夹创建到脚本执行的全过程,帮助用户实现数据库的自动备份,需要的朋友可以参考下
    2024-11-11
  • MySQL数据库多表操作通关指南(外键约束和多表联合查询)

    MySQL数据库多表操作通关指南(外键约束和多表联合查询)

    看再多的资料不如自己亲自动手实战,往往实战才能渗透知识,下面这篇文章主要给大家介绍了关于MySQL数据库多表操作的相关资料,包含外键约束和多表联合查询等,需要的朋友可以参考下
    2022-06-06
  • MySQL存储时间类型选择的问题讲解

    MySQL存储时间类型选择的问题讲解

    今天小编就为大家分享一篇关于MySQL存储时间类型选择的问题讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • MySQL8 排名窗口函数实战

    MySQL8 排名窗口函数实战

    本文阐明SQL三个排名函数处理并列名次时的区别,包括RANK()跳跃,DENSE_RANK()连续,ROW_NUMBER()分配唯一序号,下面就来详细的介绍一下,感兴趣的可以了解一下
    2026-02-02
  • mysql 超大数据/表管理技巧

    mysql 超大数据/表管理技巧

    在实际应用中经过存储、优化可以做到在超过9千万数据中的查询响应速度控制在1到20毫秒。看上去是个不错的成绩,不过优化这条路没有终点,当我们的系统有超过几百人、上千人同时使用时,仍然会显的力不从心
    2013-03-03
  • MySQL如何判断字符串为NULL或者为空字符串

    MySQL如何判断字符串为NULL或者为空字符串

    这篇文章主要介绍了MySQL如何判断字符串为NULL或者为空字符串,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • MySQL左联多表查询where条件写法示例

    MySQL左联多表查询where条件写法示例

    这篇文章主要介绍了MySQL左联多表查询where条件写法示例,本文直接给出写法示例,需要的朋友可以参考下
    2015-02-02
  • mySQL 8.0.33安装指南(推荐)

    mySQL 8.0.33安装指南(推荐)

    本文提供MySQL8.0.33的详细安装步骤,从解压安装包到设置系统服务、配置远程访问及安全设置等,包括创建和配置MySQL用户,设置环境变量,初始化数据库等关键操作,同时强调安全性的重要性,如设置强密码、限制远程访问权限,并建议在重要操作前进行数据库备份
    2024-10-10

最新评论