mysql事务和日志文件有什么关系_mysql redo undo原理说明

1次阅读

mysql通过两阶段提交(2pc)协调redo log与binlog:prepare阶段写入并标记redo log为prepare;commit阶段写入binlog后通知innodb完成提交,确保崩溃恢复和主从一致。

mysql事务和日志文件有什么关系_mysql redo undo原理说明

事务提交时,redo log 和 binlog 怎么协同写入?

MySQL 用两阶段提交(2PC)确保事务在 redo logbinlog 中状态一致。否则主从同步或崩溃恢复时会出现数据不一致。

  • 第一阶段(prepare):InnoDB 将事务的 redo log 写入磁盘,并标记为 PREPARE 状态;此时事务尚未真正提交
  • 第二阶段(commit):Server 层将该事务的完整逻辑操作写入 binlog 文件;成功后通知 InnoDB 执行 commitredo log 状态改为 COMMIT
  • 如果 crash 发生在 prepare 后、binlog 写入前:重启后发现 redo log 是 prepare 状态但无对应 binlog,则回滚该事务
  • 如果 crash 发生在 binlog 写入后、InnoDB commit 前:重启后发现有 binlogredo log 是 prepare 状态,则重放并 commit —— 这保证了主从复制和恢复的一致性

undo log 不是“redo 的反向”,它到底存什么、什么时候删?

undo log 存的是“逻辑前镜像”:比如 UPDATE t SET a=5 WHERE id=1,对应的 undo 就是一条 UPDATE t SET a=旧值 WHERE id=1,不是物理页还原。

  • INSERT 产生的 undo 是 delete(逻辑删除该行)
  • UPDATE/DELETE 产生的 undo 是反向 UPDATE(恢复字段旧值)
  • 事务提交后,undo log 不会立即删除:MVCC 需要它提供历史版本,只有当所有活跃事务(包括长事务)都不再需要该版本时,purge 线程才会清理
  • 若存在运行超 1 小时的事务,它可能拖慢整个 undo 空间回收,导致 innodb_undo_log_truncate 失效、ibdata1 持续膨胀

为什么 redo log 要顺序写、固定大小、循环覆盖?

因为它是为 crash-safe 和高性能设计的物理日志,不是归档用途。

  • innodb_log_file_size × innodb_log_files_in_group 决定了总大小(如 48MB),写满后从头覆盖 —— 这避免了随机写和文件增长开销
  • 顺序追加写 ib_logfile0/ib_logfile1,比随机刷脏页快一个数量级;配合 innodb_flush_log_at_trx_commit=1(默认)可保障每次 commit 都 fsync 到磁盘
  • 但要注意:innodb_log_file_size 太小会导致频繁 checkpoint,加剧 I/O 压力;太大则 crash 恢复时间变长(需重放更多日志)
  • 修改该参数必须停库,且要先 mysqld --innodb-redo-log-init 初始化新日志文件,否则启动失败

binlog 格式选 ROW 还是 STATEMENT?别只看文档说的“一致性”

生产环境几乎必须用 ROW,但代价真实:大事务可能让 binlog_cache_size 溢出到磁盘,拖慢提交速度。

  • STATEMENT 在含 NOW()UUID()@user_var 等非确定函数时,主从执行结果必然不同
  • ROW 记录每一行变更前后的完整镜像(含主键),主从严格一致,但单条 UPDATE 影响 10 万行 → binlog 写入 10 万条记录
  • 若遇到大事务卡顿,先查 SHOW PROCESSLIST 是否卡在 Writing to netWriting binlog;再确认 binlog_cache_disk_use 是否飙升 —— 是的话,临时调大 binlog_cache_size(如从 32K→2M)可缓解
  • MIXED 并不智能:它对某些语句仍强制用 STATEMENT,隐患难排查,不如明确选 ROW + 监控 binlog 日志体积增长速率

真正容易被忽略的点是:redo logbinlog 分属存储引擎层与 Server 层,它们的刷盘时机、缓存机制、错误处理完全独立 —— 所以不能靠其中一个推断另一个是否落盘成功。调试事务异常时,得同时查 show engine innodb status(看 redo 状态)和 show binary logs(看 binlog 位置),缺一不可。

text=ZqhQzanResources