mysql事务提交
1、
当事务commit时,需要将事务状态设置为COMMIT状态,这里同样通过Undo来实现的
入口函数:trx_commit_low-->trx_write_serialisation_history
trx_undo_set_state_at_finish
2、
二阶段提交流程
时间点1 |
prepare 阶段 |
时间点2 |
commit 阶段 |
时间点3 |
时间点1出现问题
这个时候redo log 和 binlog都在内存中,所以本次事务的相关操作都会消失,相对于事务回滚了,不影响数据的一致性。
时间点2出现问题
这个时候redo log已经到磁盘了。binlog没有刷到磁盘所以会消失。服务器从故障中恢复时,读取磁盘中的redo log ,但是由于对应的redo log项还是prepare状态,就要判断binlog 是否完整,如果binlog完整则提交事务,如果binlog不完整则回滚事务。
时间点3出现问题。
这个时候redo log 和 binlog都已经存磁盘,服务器从redo log恢复就好了。
binlog怎么判断完整性:
- statement 格式的 binlog,最后会有 COMMIT;
- row 格式的 binlog,最后会有一个 XID event
redolog 和binlog怎么联系起来:
它们有一个共同的数据字段,叫 XID。
崩溃恢复的时候,会按顺序扫描 redo log:如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务。
来自 <https://www.cnblogs.com/wsw-seu/p/13215980.html>
3、
redo日志仅记录对页的物理修改,不包含事务信息,因此在崩溃恢复时单纯依靠redo日志只能进行前滚,即恢复到崩溃前的内存状态。但是这个时候有些事务还没有提交(活跃事务)需要回滚,这就需要依赖undo,undo中记录了未提交事务及修改行的原始版本,崩溃恢复时找到这些活跃事务将原始版本还原完成回滚。因此事务是否提交信息保存在undo里。
链接:https://www.zhihu.com/question/362498822/answer/951351986
4、
这些都是由事务性存储引擎来完成的,但 binlog 不在事务存储引擎范围内,而是由 MySQL Server 来记录的。
那么就必须保证 binlog 数据和 redo log 之间的一致性,所以开启了 binlog 后实际的事务执行就多了一步,如下:
先记录 undo/redo log,确保日志刷到磁盘上持久存储。
更新数据记录,缓存操作并异步刷盘。
将事务日志持久化到 binlog。
提交事务,在 redo log 中写入commit记录。
这样的话,只要 binlog 没写成功,整个事务是需要回滚的,而 binlog 写成功后即使 MySQL Crash 了都可以恢复事务并完成提交。
要做到这点,就需要把 binlog 和事务关联起来,而只有保证了 binlog 和事务数据的一致性,才能保证主从数据的一致性。
所以 binlog 的写入过程不得不嵌入到纯粹的事务存储引擎执行过程中,并以内部分布式事务(xa 事务)的方式完成两阶段提交。
5、
疑问:事务的顺序提交问题,备机回放时怎么保证顺序提交的(相关信息是怎么通过redo传递的)?
- 点赞
- 收藏
- 关注作者
评论(0)