UPDATE 语句执行时,MySQL 怎么加锁

UPDATE更新时会加锁,而对于更新前读取的数据要看具体的隔离级别,我这样理解对吗

是的,你的理解是正确的!在 UPDATE 语句执行时,MySQL 会加锁 ,而对于 更新前读取的数据 ,则需要根据具体的 事务隔离级别 来决定事务在执行时读取到的值。

让我们具体分析一下:

1. UPDATE 语句的加锁行为

  • UPDATE 语句执行时会加锁
    • 当你执行 UPDATE 语句时,MySQL 会在被更新的行上加上 排他锁(Exclusive Lock),这意味着其他事务在当前事务提交之前不能修改这行数据。这是为了防止数据的并发修改导致不一致的结果。
    • 排他锁行级锁,它保证了当前事务对某行数据的独占访问,直到事务提交或回滚。

2. 更新前读取的数据与隔离级别的关系

  • 事务隔离级别 影响一个事务在执行时读取到的数据内容。在 MySQL 中,不同的隔离级别对读取操作有不同的影响,具体表现为:

(1) 读未提交 (READ UNCOMMITTED)

  • SELECT 操作 :可以读取其他事务未提交的数据,称为 脏读
  • UPDATE 操作:会在当前行上加排他锁(X锁),确保其他事务无法修改或读取当前正在修改的数据行。

(2) 读已提交 (READ COMMITTED)

  • SELECT 操作:事务只能读取其他事务已经提交的数据,也就是不会读取到脏数据。
  • UPDATE 操作:同样会加排他锁,确保其他事务不能修改正在更新的数据。
  • 对于更新前的数据 :事务A的 UPDATE 操作会基于它在 SELECT 之前读取到的数据来进行更新,因此事务B在执行 SELECT 时,会看到事务A已提交的数据(如果事务A已提交)。但如果事务A尚未提交,事务B不能读取事务A的未提交数据。

(3) 可重复读 (REPEATABLE READ)

  • SELECT 操作:事务A开始后,它会获得数据的快照。在整个事务的生命周期内,事务A每次读取同一行数据时都会看到相同的值。即使其他事务修改了数据,事务A也看不到这些更改,直到它提交。
  • UPDATE 操作 :事务A会对更新的数据行加排他锁,并确保数据的一致性。在 REPEATABLE READ 隔离级别下,事务B在执行时也会看到事务A开始时的数据快照,即使事务A提交了它对数据的修改,事务B也无法读取到事务A尚未提交的更改。

(4) 串行化 (SERIALIZABLE)

  • SELECT 操作:事务会在执行时加锁,确保不会发生其他事务插入、修改或删除当前事务正在读取的数据。
  • UPDATE 操作:执行时会加排他锁,确保数据的一致性。由于事务被完全串行化,事务B不会看到事务A未提交的任何更改,直到事务A完全提交。

总结

  • UPDATE 语句执行时会加锁:它会加上排他锁,防止其他事务对正在更新的数据行进行修改。排他锁确保数据的一致性。

  • 读取的数据会根据事务隔离级别不同而不同

    • READ COMMITTEDREPEATABLE READ 隔离级别下,事务的读取行为受到事务开始时快照的控制。
    • REPEATABLE READ 下,即使其他事务修改了数据,事务A始终读取自己开始时的快照数据;但如果事务B在事务A提交之前修改了数据,事务A不会看到事务B的修改。

你理解的"UPDATE 更新时会加锁,而对于更新前读取的数据要看具体的隔离级别"是完全正确的!加锁 主要发生在 UPDATE 语句执行时,而事务读取的数据视乎 隔离级别 如何设置。希望这个解释更加清楚了!如果你有进一步的问题,随时告诉我!

好的,接下来我们根据 MySQL 中的四种事务隔离级别来分析 id=1k 值在事务 B 提交后的变化。

情境概述

假设我们有以下的初始数据:

sql 复制代码
CREATE TABLE t (
    id INT PRIMARY KEY,
    k INT
);

INSERT INTO t (id, k) VALUES (1, 1), (3, 3);

事务 A 和 事务 B 的操作

  1. 事务 A (T A)

    sql 复制代码
    UPDATE t SET k = 3 WHERE id = 1;
    COMMIT;
    • 事务 A 在执行时更新了 id=1k 值为 3,但 事务 A 未提交,并且在题目中提到事务 A 在提交前被阻塞。
  2. 事务 B (T B)

    sql 复制代码
    SELECT * FROM t WHERE id = 1;
    UPDATE t SET k = k + 1 WHERE id = 1;
    COMMIT;
    • 事务 B 在事务 A 执行 UPDATE 后,执行了 SELECT 查询,接着对 id=1 的记录执行 UPDATE,将 k 增加 1。

    由于事务 A 被阻塞,事务 B 执行时 事务 A 还没有提交 。事务 B 执行时将读取到 事务 A 修改前的数据,根据不同的事务隔离级别,事务 B 会看到不同的数据值。

事务隔离级别的影响

1. READ UNCOMMITTED(读未提交)

  • SELECT 查询 :事务 B 可以看到其他事务的未提交数据,也就是 脏读 。因此,事务 B 会看到事务 A 已经修改但还未提交的 k=3
  • UPDATE 执行 :事务 B 在看到 k=3 后,会执行 UPDATE t SET k = k + 1 WHERE id = 1;,将 k3 更新为 4

结果k=4(事务 B 执行完 UPDATE 后提交,最终值为 4

2. READ COMMITTED(读已提交)

  • SELECT 查询 :事务 B 在执行 SELECT 时,只能看到事务 A 已提交的数据 。由于事务 A 还没有提交,事务 B 会看到 k=1(即事务 A 修改前的数据)。
  • UPDATE 执行 :事务 B 执行 UPDATE t SET k = k + 1 WHERE id = 1;,将 k1 更新为 2
  • 事务 A 提交后 :事务 A 提交时,k 被更新为 3,但事务 B 在自己的提交后,k 不会变成 3,因为事务 B 在查询时只读取到事务 A 提交前的值。

结果k=3(事务 B 提交后,事务 A 提交时,k 被更新为 3

3. REPEATABLE READ(可重复读)

  • SELECT 查询 :事务 B 会看到事务 A 开始时的 数据快照 ,即 k=1 ,即使事务 A 已经将 k 修改为 3。事务 B 在其生命周期内会一直读取到 k=1
  • UPDATE 执行 :事务 B 执行 UPDATE t SET k = k + 1 WHERE id = 1;,将 k1 更新为 2
  • 事务 A 提交后 :由于事务 A 提交时 k 被更新为 3,但事务 B 依然以自己的快照为准,所以事务 B 不会受到事务 A 提交后的更新影响。

结果k=3(事务 B 提交后,k 的最终值会是 3,因为事务 A 提交时的 k=3 覆盖了事务 B 的 UPDATE

4. SERIALIZABLE(串行化)

  • SELECT 查询 :事务 B 执行 SELECT 时,会读取到事务 A 开始时的 数据快照 (即 k=1)。
  • UPDATE 执行 :事务 B 执行 UPDATE,同样会基于 k=1 执行,将 k 更新为 2
  • 事务 A 提交后 :事务 A 提交后,k 更新为 3,但是因为 串行化 隔离级别会强制事务串行化执行,事务 B 必须等到事务 A 提交后才能执行其查询操作和更新操作,因此事务 B 在提交前必须等待事务 A 提交。

结果k=3(事务 B 提交后,最终值为 3,并且事务 A 提交时修改的值会生效)

总结

隔离级别 事务B提交后的 k
READ UNCOMMITTED k = 4
READ COMMITTED k = 3
REPEATABLE READ k = 3
SERIALIZABLE k = 3

解释:

  • READ UNCOMMITTED :由于允许脏读,事务 B 读取到事务 A 未提交的修改,最终 k = 4
  • READ COMMITTED :事务 B 只读取事务 A 提交的数据,由于事务 A 未提交,它读取到的是 k=1,然后修改为 k=2。但事务 A 提交后,k 被更新为 3
  • REPEATABLE READ :事务 B 读取的是事务开始时的快照数据,即 k=1,修改后 k=2。事务 A 提交后,k 变为 3
  • SERIALIZABLE :事务 B 在事务 A 提交后才开始执行,最终 k 变为 3

希望这个分析清楚地帮助你理解了在不同事务隔离级别下,事务 B 提交后的 k 值如何变化。如果有其他问题,欢迎继续提问!

相关推荐
utmhikari11 分钟前
【架构艺术】Go语言微服务monorepo的代码架构设计
后端·微服务·架构·golang·monorepo
蜡笔小新星14 分钟前
Flask项目框架
开发语言·前端·经验分享·后端·python·学习·flask
计算机学姐18 分钟前
基于Asp.net的驾校管理系统
vue.js·后端·mysql·sqlserver·c#·asp.net·.netcore
欢乐少年19042 小时前
SpringBoot集成Sentry日志收集-3 (Spring Boot集成)
spring boot·后端·sentry
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
uhakadotcom7 小时前
Apache CXF 中的拒绝服务漏洞 CVE-2025-23184 详解
后端·面试·github
uhakadotcom7 小时前
CVE-2025-25012:Kibana 原型污染漏洞解析与防护
后端·面试·github
uhakadotcom7 小时前
揭秘ESP32芯片的隐藏命令:潜在安全风险
后端·面试·github
uhakadotcom7 小时前
Apache Camel 漏洞 CVE-2025-27636 详解与修复
后端·面试·github
uhakadotcom7 小时前
OpenSSH CVE-2025-26466 漏洞解析与防御
后端·面试·github