MySQL 事务与稳定性
本文最后更新于 2025年9月5日 凌晨
事务
事务可以理解为对一系列读写操作的抽象。在单体架构中,数据库通常作为系统的一个统一组件,直接为业务服务。在这种场景下,一次数据的读写请求(例如 SQL 查询)通常对应一次数据库调用:
1 | |
这是一个同步过程,应用会等待数据库返回结果,然后继续执行后续逻辑。
然而在分布式或微服务架构中,数据往往分散存储在不同的服务节点上。当一个业务操作涉及多个服务的数据修改时,就需要确保这些操作要么全部成功,要么全部失败,从而保证跨服务的数据一致性。这就是分布式事务要解决的问题。
分布式事务的实现方式可以是同步的,也可以是异步的,但其核心目标始终是 在分布式环境下维护数据的一致性和原子性 。
原子性 :
MySQL中的数据稳定性保证
事务的支持
在Mysql中 通过BEGIN或START TRANSACTION 开启一个事务,在默认情况下AUTOCOMMIT 设置为1 ,意味着每一个Mysql语句本身就是一次事务处理。
开启事务
1 | |
或
1 | |
当 开启事务后,当前终端的autocommit 被设置为false。
而当使用ddl 语句后,会将之前的语句自动提交
事务的稳定保证
原子性
即 事务的过程是一个原子过程,要么全部成功,要么全部失败。(undo log)
持久性
一旦事务提交,则其所做的修改会永久保存到数据库中,此时即使系统崩溃,修改的数据页不会丢失(redo log)
一致性
数据库总是从一个一致性的状态转换到另一个一致性的状态
隔离性
即 在事务中执行的修改操作不影响其他事务的操作。 (锁+mvcc)
稳定性场景
对于数据库服务来说,影响服务稳定性的有以下几种场景
- 处理sql请求回退,撤销事务中的配置修改
- 服务的异常崩溃,由于各种原因导致服务的异常退出/重启
- 数据的迁移,恢复
- 集群数据的同步
MySQL中的日志
日志
在应用程序中,日志提供的主要是程序执行过程的状态打印。但是在中间件中日志可以被理解为“请求”的快照,以Mysql为例,Mysql对于 数据请求需要经过 连接器-分析器-优化器-执行器,最终由执行器调用存储引擎,完成SQL命令的执行。那么通过日志将请求和变更记录下来,就可以达到使用日志进行数据恢复的目的。
undo log
在InnoDB中,使用undo log 实现事务请求的撤销。
每对一条记录进行一次改动,就会对应着一条undo log
undo log 用于事务执行时的回滚操作,保证事务的原子性。
undo log 会在命令执行时创建一条对应的回退指定存储到undo页中
1 | |
redo log
在InnoDB中,使用redo log 完成数据的恢复过程。
1 | |
在一次事务过程中,产生的redo log必须是一个完整的组,只有读取到最终的结束标志,才会使用对应的redo log进行恢复。
redo log写满后,MySQL不再执行新的更新操作,MySQL 进行阻塞,此时会停下来将buffer pool中的脏页刷新到磁盘中,然后标记redo log 哪些记录可以擦除,接着对旧的redo log记录进行擦除,等擦除完旧记录,MySQL恢复正常运行(checkpoint)通过一个线程进行 脏页存盘工作,另一个线程检查脏页处理情况,并标记对应的redo log可以被覆盖
落盘时机 :
- 事务提交时
- InnoDB后台线程
- 写入redo log量已经占满总容量的50%
- checkpoint 落盘
- 服务关闭时
binlog
binlog 由执行器产生,它用于恢复数据库数据。
binlog可以以以下三种形式进行存储
1 | |
binlog文件创建时机:
- 系统重启
- 文件大小超过1G
- 执行flush logs
数据恢复
1 | |
备份
1 | |
数据复制
主从配置
1 | |
集群配置
1 | |
binlog写入过程 → binlog cache →pagecache
设置sync_binlog
sync_binlog = 0 每次提交事务都write,不fsync,由操作系统决定何时fsync
sync_binlog = 1 每次提交事务都write,然后马上执行fsync
sync_binlog = N 每次提交事务都write,但积累N个事务才fsync
两阶段提交

1. 事务开始阶段
1 | |
2. DML操作执行阶段
对于每个DML操作(INSERT/UPDATE/DELETE):
1 | |
具体流程:
- 写undo log :首先记录原始数据,用于回滚
- 修改Buffer Pool :在内存中修改数据页
- 写redo log buffer :记录修改操作,用于崩溃恢复
3. 查询执行
1 | |
4. 事务提交阶段(关键)
这是最复杂的阶段,涉及 两阶段提交 :
Prepare阶段
1 | |
Commit阶段
1 | |