事务协调者(PM) , 事务参与者(TM)
两阶段提交分为
1. 准备(prepare)
pm发消息询问所有TM是否都准备好:
各个tm做本地事务的预操作(如写日志),不提交
回复pm 1. yes:准备好了 2. no: 没准备好
2.提交(commit)
tm:
根据yes或者no,发消息通知所有tm执行提交事务或者回滚事务,然后tm回复ack
分布式事务结束
做一个比较:
TCC(Try-Confirm-Cancel)
- Try:执行预操作,保留资源,但不提交。
- Confirm:所有参与者确认预操作,进行实际提交。
- Cancel:如果任何参与者未准备好,则执行补偿操作,撤销之前的预操作。
两阶段提交(2PC)
- Prepare:协调者询问所有参与者是否准备好,参与者执行预操作并返回状态(是或否)。
- Commit:根据参与者的回复,协调者决定:
- 如果所有参与者都准备好,发送提交指令。
- 如果有参与者不准备,发送回滚指令。
下面是mysql两阶段提交的场景
1. Prepare 阶段
在这个阶段,MySQL 执行以下操作:
- 写入 XID:将内部 XA 事务的 ID(XID)写入 redo log,记录下该事务的标识。
- 设置状态为 Prepare:在 redo log 中将该事务的状态设置为 "prepare",表示事务已准备好,可以进行提交。
- 持久化到磁盘:确保 redo log 已经被写入到磁盘,确保在系统崩溃时能够恢复该事务的状态。
2. Commit 阶段
在准备阶段之后,如果所有参与者都反馈可以提交,MySQL 进入 commit 阶段,执行以下操作:
- 写入 XID 到 binlog:将该事务的 XID 写入 binlog,记录下该事务的提交信息。
- 持久化 binlog 到磁盘:确保 binlog 已经被写入到磁盘,确保数据的持久性和可恢复性。
- 更新 redo log 状态:将 redo log 中该事务的状态设置为 "commit",表示该事务已经成功提交。
3. 提交标识
在 MySQL 中,事务的提交成功是以 binlog 中的 XID 写入成功作为标识:
崩溃重启后,mysql 查找 prepare 状态redo_log,在binlog中查找XID
- 如果 binlog 中没有当前 XA 事务的 XID:则表示事务未成功提交,MySQL 会进行回滚操作,撤销该事务的所有变更。
- 如果 binlog 中有当前 XA 事务的 XID:则表示事务成功提交,MySQL 会确认并保留该事务的变更。
1. 协调者 (Transaction Manager, PM)
- 职责:在MySQL的上下文中,协调者通常是数据库系统本身,负责管理和协调分布式事务的状态。
- 工作流程:
- 准备阶段 (Prepare Phase):
- 协调者向所有参与者(即各个数据库实例)发送准备请求。
- 各参与者执行本地事务的预操作,通常是写入日志但不提交,并回复协调者其准备状态(是/否)。
- 协调者将XID(事务ID)写入redo log,并将状态设置为prepare。
- 提交阶段 (Commit Phase):
- 协调者接收到所有参与者的准备确认后,将XID写入binlog,持久化到磁盘,并通知参与者提交事务。
- 如果有参与者回复未准备好,协调者会请求所有参与者回滚事务。
- 准备阶段 (Prepare Phase):
2. 参与者 (Transaction Participants, TM)
- 职责:参与者是具体执行操作的数据库实例,负责处理本地的事务逻辑。
- 工作流程:
- 准备阶段:
- 每个参与者接收到协调者的准备请求后,执行本地的事务逻辑,做必要的预处理(如写入本地日志),然后返回准备状态。
- 提交阶段:
- 如果收到协调者的提交请求,参与者将执行实际的提交操作,将变更持久化到数据库。
- 如果收到回滚请求,参与者会撤销本地事务的变更。
- 准备阶段: