Mysql如果在执行事务过程中宕机了怎么办?

本文深入探讨InnoDB存储引擎中的redolog与undolog机制,阐述其如何保障事务的原子性、一致性和持久性,以及在系统恢复中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://www.cnblogs.com/zhiqian-ali/p/5668199.html

redo log

在innoDB的存储引擎中,事务日志通过重做(redo)日志和innoDB存储引擎的日志缓冲(InnoDB Log Buffer)实现。事务开启时,事务中的操作,都会先写入存储引擎的日志缓冲中,在事务提交之前,这些缓冲的日志都需要提前刷新到磁盘上持久化,这就是DBA们口中常说的“日志先行”(Write-Ahead Logging)。

当事务提交之后,在Buffer Pool中映射的数据文件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机,那么当系统重启进行恢复时,就可以根据redo log中记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务,可以继续提交,也可以选择回滚,这基于恢复的策略而定。
在系统启动的时候,就已经为redo log分配了一块连续的存储空间,以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起。如下一个简单示例:

记录1:<trx1, insert...>
记录2:<trx2, delete...>
记录3:<trx3, update...>
记录4:<trx1, update...>
记录5:<trx3, insert...>

undo log

undo log主要为事务的回滚服务。在事务执行的过程中,除了记录redo log,还会记录一定量的undo log。undo log记录了数据在每个操作前的状态,如果事务执行过程中需要回滚,就可以根据undo log进行回滚操作。单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。

以下是undo+redo事务的简化过程:

假设有2个数值,分别为A和B,值为1,2

1. start transaction;
2. 记录 A=1 到undo log;
3. update A = 3;
4. 记录 A=3 到redo log;
5. 记录 B=2 到undo log;
6. update B = 4;
7. 记录B = 4 到redo log;
8. 将redo log刷新到磁盘
9. commit

在1-8的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务提交,因为此时redo log已经持久化。若在9之后系统宕机,内存映射中变更的数据还来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘。

所以,redo log其实保障的是事务的持久性和一致性,而undo log则保障了事务的原子性。

### MySQL 中 `UPDATE` 语句的执行过程和原理解析 #### 1. **开启事务** 当客户端发送一条 `UPDATE` 语句到服务器时,MySQL 首先会判断当前是否处于显式事务中。如果未指定事务,则默认启动一个隐式事务[^3]。 #### 2. **SQL 解析** 接收到 SQL 请求后,MySQL 的解析器会对该语句进行语法分析,验证其合法性并将其转换为内部表示形式。此阶段还会检查表名、列名以及条件表达式的正确性[^4]。 #### 3. **查询计划生成** 优化器负责生成最佳的执行计划。对于 `UPDATE` 操作来说,它需要决定如何高效地定位满足 `WHERE` 条件的数据行。可能涉及索引的选择或者全表扫描等方式来找到目标记录集[^2]。 #### 4. **查询要修改的数据** 基于上一步产生的访问路径,存储引擎实际读取符合条件的行数据进入内存缓冲区以便进一步处理。如果是 InnoDB 存储引擎,在这个过程中可能会加载对应的聚簇索引来加速查找效率[^3]。 #### 5. **校验与权限检查** 在真正更改任何数据之前,系统还需要再次确认操作的安全性和有效性,比如用户是否有足够的权限去改变这些特定字段上的值;另外也会做些额外逻辑检测防止非法输入等问题发生[^1]。 #### 6. **加锁机制应用** 为了保证并发环境下的数据一致性,InnoDB 使用行级锁定策略对即将被改动的目标行施加 X 锁 (exclusive lock),阻止其他事务同时对该资源做出冲突性的变更尝试直到本笔交易完成为止[^3]。 #### 7. **修改数据及生成重做日志( redo log )** 一旦获取必要的锁保护之后就可以安全地实施预定的变化动作了——即按照设定的新值替换旧有属性内容,并同步写入相应的 undo/redo 日志文件用于后续恢复用途或支持 MVCC 特性实现等等[^4]。 #### 8. **本地提交** 所有上述准备工作完成后便可以正式宣告此次更新行动结束并通过 COMMIT 命令通知整个数据库实例接受这一系列变动作为永久状态的一部分保存下来[^3]。 #### 9. **主从复制 & 脏页刷新** 最后但同样重要的是,如果有配置好的 Slave 实例存在的话则需及时推送 Binlog 给它们以维持集群间的一致性水平;与此同时后台线程也将定期把驻留在 Buffer Pool 当中的“脏页面”持久化回磁盘上去确保即使遇到意外宕机也能最大程度挽回损失[^3]。 ```python # 示例 Python 连接 MySQL执行 Update 语句 import mysql.connector conn = mysql.connector.connect( host="localhost", user="root", password="password", database="testdb" ) cursor = conn.cursor() update_query = """ UPDATE tb_student A SET A.age='19' WHERE A.name='张三'; """ try: cursor.execute(update_query) conn.commit() # 提交事务 except Exception as e: conn.rollback() # 出错时回滚 finally: cursor.close() conn.close() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值