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) 冲突 兼容 兼容 兼容
相关推荐
三分恶4 分钟前
支付新手常犯的十个错误
后端
珹洺7 分钟前
数据库系统概论(十六)数据库安全性(安全标准,控制,视图机制,审计与数据加密)
数据库·安全·oracle
清风细雨_林木木8 分钟前
数据库 MongoDB (NoSQL) 与 MySQL (SQL) 的写法对比
数据库·mongodb·nosql
小陈又菜16 分钟前
SQL Transactions(事务)、隔离机制
数据库·sql·事务·隔离机制
Java中文社群23 分钟前
超实用!Dify快速接入本地MCP服务
java·人工智能·后端
月忆36425 分钟前
Go语言的context
后端·golang
forestsea35 分钟前
PostgreSQL 安全纵深防御:从权限到加密
数据库·安全·postgresql
湿物男37 分钟前
mysql核心知识点
数据库·mysql·adb
RainbowSea43 分钟前
6-2 MySQL 数据结构选择的合理性
java·后端·mysql
喝养乐多长不高1 小时前
深入探讨redis:缓存
数据库·redis·缓存·缓存穿透·缓存击穿·缓存雪崩·缓存预热