MySQL 事务的二阶段提交是什么?
二阶段提交(Two-Phase Commit, 2PC)是分布式事务中的一种协调协议,用于确保多个资源(如数据库或数据节点)在事务提交时保持一致性。MySQL 在存储引擎(如 InnoDB)和 Binlog(归档日志)之间使用二阶段提交来保证事务的一致性。
在 MySQL 中,二阶段提交的典型场景是协调 InnoDB 的事务日志(redo log) 和 Binlog 的写入,以确保事务既能满足崩溃恢复需求,又能保证主从复制的一致性。
二阶段提交的流程
二阶段提交分为两个阶段:
1. 准备阶段(Prepare Phase)
- MySQL 将事务的修改写入 InnoDB 的 redo log,并将 redo log 标记为 "PREPARED" 状态。
- 此时,数据的实际修改还没有被提交,事务处于“可恢复”状态(可以通过 redo log 恢复未完成的事务)。
- 如果发生异常,可以回滚事务。
2. 提交阶段(Commit Phase)
- MySQL 将事务写入 Binlog(记录事务的持久性变更,用于主从复制)。
- 在确保 Binlog 写入成功后,更新 redo log 的状态为 "COMMITTED"。
- 此时,事务正式提交,数据对其他事务可见。
二阶段提交的作用
-
一致性保证:
二阶段提交确保了 InnoDB 的事务日志和 Binlog 之间的一致性。如果 Binlog 写入失败,可以通过回滚撤销未完成的事务。 -
主从复制的一致性:
Binlog 用于主从复制。如果没有二阶段提交,可能会导致主库和从库数据不一致的问题。 -
崩溃恢复:
如果 MySQL 在事务提交中途崩溃,redo log 的 "PREPARED" 状态可以帮助事务在恢复时判断是提交还是回滚。
二阶段提交的工作示例
假设一个事务执行以下操作:
- 修改一个用户的余额。
- 插入一条记录到交易日志表。
执行流程:
- Prepare 阶段:
- 将修改写入 redo log 并标记为 "PREPARED"。
- 此时,事务未提交,但可以通过 redo log 恢复状态。
- Commit 阶段:
- 将事务写入 Binlog。
- 确认 Binlog 写入成功后,将 redo log 标记为 "COMMITTED"。
- 事务完成。
示例代码
假设有一个 transactions
表用于记录交易数据:
CREATE TABLE transactions (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
事务的执行如下:
BEGIN;
UPDATE users SET balance = balance - 100 WHERE id = 1;
INSERT INTO transactions (user_id, amount) VALUES (1, -100);
此时,进入二阶段提交的流程
1. InnoDB 记录修改到 redo log 并标记为 PREPARED
2. MySQL 写入 Binlog
3. 更新 redo log 状态为 COMMITTED
COMMIT;
总结
二阶段提交在 MySQL 中的核心目标是保证 InnoDB 的事务日志和 Binlog 之间的数据一致性。在分布式场景中,二阶段提交也是解决分布式事务一致性的重要协议。虽然二阶段提交提供了数据一致性的保障,但它会引入一定的性能开销,因此在实际使用中需要权衡性能与一致性需求。
标签:Binlog,事务,log,提交,MySQL,redo From: https://www.cnblogs.com/eiffelzero/p/18608653