解读Mysql中的共享锁,排它锁与意向锁

共享锁与排它锁

本文执行的事务都在repeatable read隔离级别(mysql8 下的默认级别)下执行的

假设有一个 accounts 表:

diff 复制代码
+----+---------+
| id | balance |
+----+---------+
|  1 | 1000.00 |
|  2 |  500.00 |
+----+---------+

共享锁

测试 1: 被锁行在事务提交前只能被读取, 其他进程无法修改被锁行数据

Shell A Shell B
start transaction;
select * from accounts where id=1 for share;
start transaction;
select * from accounts where id=1;
正常出结果
update accounts set balance=balance+100 where id=1;
暂停执行, 等待 Shell A 提交
commit; (自动执行 update 语句)

测试 2: 被锁行在事务提交前, 其他进程可正常添加共享锁, 但无法修改行数据

Shell A Shell B
start transaction;
select * from accounts where id=1 for share;
start transaction;
select * from accounts where id=1 for share;
正常出结果,并获取共享锁
update accounts set balance=balance+100 where id=1;
暂停执行, 等待 Shell A 提交
commit; (自动执行 update 语句)

测试 3: 被锁行在事务提交前, 其他进程无法添加排他锁

Shell A Shell B
start transaction;
select * from accounts where id=1 for share;
start transaction;
select * from accounts where id=1 for update;
暂停执行, 等待 Shell A 提交
commit; (自动执行 select 语句)

测试 4: 被锁行在事务内执行了非 select 语句, 在事务提交前, 其他进程无法添加共享锁或排它锁.(排它锁这里没有案例, 但共享锁都加不了, 排它锁肯定也加不了)

Shell A Shell B
start transaction;
update accounts set balance=balance+100 where id=1;
start transaction;
select * from accounts where id=1 for share;
暂停执行, 等待 Shell A 提交
commit; (自动执行 select 语句)

排它锁

测试 1: 被锁行在事务提交前, 其他进程只能读取, 无法修改被锁行数据

Shell A Shell B
start transaction;
select * from accounts where id=1 for update;
select * from accounts where id=1;
正常出结果
update accounts set balance=balance+100 where id=1;
暂停执行, 等待 Shell A 提交
commit; (自动执行 update 语句)

测试 2: 被锁行在事务提交前, 其他进程不能添加共享锁

Shell A Shell B
start transaction;
select * from accounts where id=1 for update;
start transaction;
select * from accounts where id=1 for share;
暂停执行, 等待 Shell A 提交
commit; (自动执行 select 语句)

测试 3: 被锁行在事务提交前, 其他进程不能添加排他锁

Shell A Shell B
start transaction;
select * from accounts where id=1 for update;
start transaction;
select * from accounts where id=1 for update;
暂停执行, 等待 Shell A 提交
commit; (自动执行 select 语句)

意向锁

意向锁是一种用于协调并发访问的锁定机制,它不直接锁定数据,而是用于指示事务的意图,即该事务是否打算锁定数据。

考虑一个数据库中的多个表或数据行,多个事务可能需要对这些数据进行读取或修改。意向锁的作用是协助数据库系统了解事务的意向,以便更有效地管理锁定。

举个例子:

事务 A 打算对某一行数据进行写入操作,因此它会请求排他锁(Exclusive Lock)。 同时,事务 B 打算对同一行数据进行读取操作,因此它会请求共享锁(Shared Lock)。 这里的问题是,数据库系统如何知道有其他事务正在打算锁定这一行数据呢?这时就引入了意向锁:

事务 A 在请求排他锁之前会请求意向排他锁(Intent Exclusive Lock)来指示它的意向是锁定数据。 事务 B 在请求共享锁之前会请求意向共享锁(Intent Shared Lock)来指示它的意向是锁定数据。 意向锁并不直接影响数据,它只是一种标记,告诉数据库系统有哪些事务打算锁定数据。这有助于系统更好地管理并发操作,避免冲突,提高性能。

所以,意向锁是一种数据库内部的机制,用于协助事务之间的锁定协调,以确保数据的一致性和并发性。它们不是直接应用到数据上的锁定。

意向锁(Intent Lock)通常是数据库系统内部管理的,而不需要显式地添加或控制。平时主要与共享锁和排他锁打交道,而数据库系统会自动处理意向锁以协调事务之间的并发访问。

当一个事务请求共享锁或排他锁时,数据库系统会自动添加相应的意向锁。例如,当事务请求排他锁时,数据库系统会添加意向排他锁(IX 锁)以指示它的意向是锁定数据。当事务请求共享锁时,系统会添加意向共享锁(IS 锁)。

开发中只需关注获取所需的锁(共享锁或排他锁)以及正确地释放这些锁,数据库系统会负责管理和处理意向锁。

相关推荐
java1234_小锋2 小时前
【技术专题】Mysql8 数据库 - Mysql8 数据类型简介
数据库·mysql
JosieBook2 小时前
【数据库】MySQL 实战精通系列 · 第10篇:分库分表与分布式事务实战
数据库·分布式·mysql
做运维的阿瑞6 小时前
多表查询基础:INNER JOIN、LEFT JOIN、RIGHT JOIN
数据库·sql·mysql·算法
夜雪一千8 小时前
MySQL 中什么是条件注释
数据库·mysql
暖核9 小时前
MySQL 高级运维核心:备份恢复、主从复制与 MHA 高可用复习总结
运维·数据库·mysql
晚风叙码10 小时前
MySQL 表的操作:从建表到删表,一篇讲清楚
android·mysql·oracle
paopaokaka_luck11 小时前
非遗文物数字化小程序(AI非遗问答、ONNX图像识别、协同过滤推荐、ECharts数据分析、非遗知识浏览与互动、文创商城订单闭环、文化活动报名签到、社区交流)
javascript·spring boot·mysql·数据分析·echarts·mybatis
Dxy123931021611 小时前
MySQL 条件注释 vs 普通注释
数据库·mysql
做运维的阿瑞12 小时前
自连接、交叉连接与复杂 JOIN:一条问题链讲透
前端·数据库·mysql
小马同学-12 小时前
MySQL5.x源码安装
mysql