MySQL InnoDB 行锁

前言

InnoDB 行锁是 MySQL 的 InnoDB 存储引擎提供的一种锁机制,用于实现事务的并发控制,保证数据的一致性和完整性

行锁

正如其名,是对一行数据进行加锁,当一个事务 A 对记录 r 加上行锁之后,可以对记录 r 进行修改,在释放行锁之前,其他事务无法获取记录 r 的行锁进行修改。

行锁是读锁还是写锁?

行锁分为 共享锁排它锁,共享锁可以多个事务同时获取,进行读取数据;而排它锁,同一时间只能有一个事务能获取成功,获取成功之后便可对数据记录进行修改操作。

行锁

行锁类型

共享锁(S 锁)

允许事务读取一行数据。多个事务可以同时对同一行数据加共享锁,也就是共享锁之间是兼容的。

若事务 A 对某行数据加上共享锁,那么事务 B 也可以对这行数据加共享锁进行读取操作,但在所有共享锁释放之前,任何事务都不能对这行数据加排他锁进行写操作。

排他锁(X 锁)

允许事务更新或删除一行数据。一旦一个事务对某行数据加上排他锁,其他事务就不能再对这行数据加任何类型的锁,直到该排他锁被释放。

排他锁与共享锁的兼容性

排他锁(X) 共享锁(S)
排他锁(X) 冲突 冲突
共享锁(S) 冲突 兼容

可以看到的是 X锁与任何的锁都不兼容,而 S 锁仅和 S 锁兼容。

注:S 和 X 都是行锁,兼容是指对同一记录锁的兼容性情况。

加锁方式

隐式加锁

在执行 UPDATEDELETE 等修改数据的语句时,InnoDB 会自动对涉及的行记录加上排他锁。例如:

sql 复制代码
UPDATE your_table SET column1 = 'new_value' WHERE id = 1;

此语句执行时,InnoDB 会自动对 id = 1 的行记录加上排他锁。

显式加锁

可以使用特定的 SQL 语句来显式地加锁。

  • 共享锁 :使用 SELECT ... LOCK IN SHARE MODE 语句,示例如下:
sql 复制代码
SELECT * FROM your_table WHERE id = 1 LOCK IN SHARE MODE;

该语句会对 id = 1 的行记录加上共享锁。

排他锁

使用 SELECT ... FOR UPDATE 语句,示例如下:

sql 复制代码
SELECT * FROM your_table WHERE id = 1 FOR UPDATE;

此语句会对 id = 1 的行记录加上排他锁。

行锁特点

粒度小

相比于表锁,行锁的粒度更小,只对需要操作的行进行加锁,因此并发性能更高。不同事务可以同时对不同行进行操作,减少了锁冲突的概率。

开销大

行锁需要维护更多的锁信息,加锁和解锁的操作也更为复杂,因此会带来一定的性能开销。

在 InnoDB 的事务实现里,当两个事务都要对同一条数据进行修改时,持有锁的状态会持续到事务提交或者回滚,下面为你详细解释:

锁机制

InnoDB 采用了行级锁来管理并发事务对同一行数据的访问。当一个事务需要修改某条数据时,它会先尝试获取该行数据的排他锁(X 锁)。

排他锁的作用是阻止其他事务对同一行数据进行读取和修改操作,以此保证数据的一致性和完整性。

锁的持有时间

一旦事务成功获取到排他锁,就会一直持有该锁,直至事务完成。这里的事务完成有两种情况:

  • 事务提交 :当事务中的所有操作都成功执行,并且使用 COMMIT 语句提交事务时,事务会释放持有的所有锁。此时,其他事务就有机会获取该行数据的锁并进行操作。
  • 事务回滚 :若事务执行过程中出现错误或者满足特定条件需要撤销已执行的操作,使用 ROLLBACK 语句回滚事务,事务也会释放持有的所有锁。
sql 复制代码
-- 事务 1
START TRANSACTION;
-- 事务 1 获取排他锁并修改数据
UPDATE your_table SET column1 = 'new_value' WHERE id = 1;
-- 此时事务 1 持有锁,直到提交或回滚

-- 事务 2
START TRANSACTION;
-- 事务 2 尝试修改同一行数据,会被阻塞,直到事务 1 提交或回滚
UPDATE your_table SET column1 = 'another_value' WHERE id = 1;

-- 事务 1 提交
COMMIT;
-- 事务 1 释放锁,事务 2 可以继续执行并获取锁

综上所述,在 InnoDB 中,事务对锁的持有会持续到事务提交或者回滚,这样能确保并发事务对同一行数据的操作是串行化的,从而保证数据的一致性和完整性。

锁的兼容性

InnoDB 中的锁有不同的类型,并且存在锁的兼容性规则,用于管理多个事务对同一资源的并发访问。在这些规则中,排他锁和其他类型的锁是不兼容的。具体情况如下:

排他锁(X) 共享锁(S) 意向排他锁(IX) 意向共享锁(IS)
排他锁(X) 冲突 冲突 冲突 冲突
共享锁(S) 冲突 兼容 兼容 兼容
意向排他锁(IX) 冲突 兼容 兼容 兼容
意向共享锁(IS) 冲突 兼容 兼容 兼容
相关推荐
菠萝崽.8 分钟前
安装docker,在docker上安装mysql,docker上安装nginx
java·mysql·nginx·docker·软件工程·springboot·开发
极小狐9 分钟前
极狐GitLab 议题权重有什么作用?
开发语言·数据库·chrome·c#·gitlab
懵逼的小黑子1 小时前
解释两个 Django 命令 makemigrations和migrate
数据库·django
Lxinccode3 小时前
Java查询数据库表信息导出Word-获取数据库实现[1]:KingbaseES
java·数据库·word·获取数据库信息·获取kingbasees信息
豆沙沙包?4 小时前
5.学习笔记-SpringMVC(P61-P70)
数据库·笔记·学习
朴拙数科6 小时前
MongoDB Atlas与MongoDB连接MCP服务器的区别解析
服务器·数据库·mongodb
咖啡调调。6 小时前
使用Django框架表单
后端·python·django
A-Kamen6 小时前
MySQL 存储引擎对比:InnoDB vs MyISAM vs Memory
数据库·mysql·spark
白泽talk7 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务