MySQL 是如何实现事务的?
2025-05-15 09:22 阅读(41)

1. 事务锁机制

作用:保证事务的隔离性(Isolation),防止并发事务之间相互干扰。

实现:


行锁(Row-Level Lock):锁住被操作的具体数据行,提高并发性,适合大规模数据操作。

表锁(Table-Level Lock):锁住整个表,适用于批量操作或小规模数据。


流程:


事务开始时自动或显式地为操作的数据行或表加锁。

事务执行期间保持锁,防止其他事务对同一数据行或表进行修改。

事务提交或回滚后释放锁。



2. Redo Log(重做日志)

作用:确保事务的持久性(Durability)。

实现:


当事务对数据进行修改时,MySQL 会首先将这些修改记录到 redo log 中。

如果数据在写入磁盘之前系统崩溃,redo log 可以在重启后恢复未完成的修改。


流程:


事务执行修改操作时,生成 redo log 并写入日志文件。

等待事务提交后,redo log 被标记为 commit 状态。

后台线程(如 log writer 和 checkpointer)定期将 redo log 刷入磁盘。



3. Undo Log(回滚日志)

作用:


确保事务的原子性(Atomicity),允许事务回滚以撤销未完成的操作。

在多版本并发控制(MVCC)中,用于提供数据的旧版本,以支持一致性读取。


实现:


记录事务修改前的数据状态。

如果事务需要回滚,MySQL 使用 undo log 恢复到事务开始前的状态。


流程:


事务开始后,生成 undo log 记录数据的初始版本。

当事务修改数据时,undo log 保留旧版本数据。

事务提交或回滚后,undo log 被清理或保留(取决于 MVCC 的需要)。



4. MVCC(多版本并发控制)

作用:提供一致性读取(Consistent Read),实现事务隔离。

实现:


为每行数据维护多个版本(版本链)。

每个事务读取数据时,根据事务的隔离级别和开始时间,选择合适版本的数据。


流程:


事务开始时记录一个事务版本号。

读取数据时,检查数据的版本号是否与事务版本兼容,以确定读取哪个版本的数据。

对于更新操作,生成一个新的数据版本,并使用 undo log 保留旧版本。



具体事务流程

START TRANSACTION; 
-- 1. 开始事务 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 
-- (可选) 设置隔离级别 
SELECT ... FOR UPDATE; 
-- 2. 获取事务版本号、加锁、记录 redo/undo log 
UPDATE ...; 
-- 3. 执行具体操作,记录 redo/undo log 
COMMIT; 
-- 4. 提交事务,释放锁,应用 redo log


https://www.zuocode.com