2026/4/8 23:03:08
网站建设
项目流程
舟山 网站制作,网站伪静态文件,怎么做能让网站尽快收录,网站后台发布了但看不见MySQL 事务执行链不是“BEGIN → SQL → COMMIT”#xff0c;而是一条跨越连接层、SQL 层、存储引擎层、日志系统、锁管理器的精密协作路径。一、事务执行的 5 个阶段#xff08;以 START TRANSACTION 到 COMMIT 为例#xff09;
1. 事务启动 → 2. 语句执行 → 3. 写日志 →…MySQL 事务执行链不是“BEGIN → SQL → COMMIT”而是一条跨越连接层、SQL 层、存储引擎层、日志系统、锁管理器的精密协作路径。一、事务执行的 5 个阶段以START TRANSACTION到COMMIT为例1. 事务启动 → 2. 语句执行 → 3. 写日志 → 4. 提交 → 5. 清理阶段 1事务启动START TRANSACTION/ 第一条 SQL分配事务 IDtrx_id从全局递增的trx_sys-max_trx_id获取分配回滚段Rollback Segment用于存储 undo 日志事务对象入活跃列表trx_sys-trx_list供 MVCC 和锁管理使用。 此时无任何磁盘 I/O纯内存操作。阶段 2DML 语句执行如UPDATE users SET nameA WHERE id11SQL 层解析与优化语法分析 → 生成 AST优化器选择执行计划如走主键索引生成执行器迭代器handler接口调用。2存储引擎层InnoDB操作加锁主键id1→ 加X 锁排他锁若无索引全表扫描 → 加大量行锁危险。查数据先查 Buffer Pool内存未命中 → 从磁盘加载页到 Buffer Pool。写 undo log内存记录修改前的值nameOld用于回滚和 MVCC旧版本可见性。修改数据页在 Buffer Pool 中修改nameA标记页为“脏页”dirty page但不刷盘。关键此时修改仅在内存事务未提交其他事务不可见通过 MVCC 隔离。阶段 3日志写入WAL 机制InnoDB 遵循Write-Ahead LoggingWAL日志必须先于数据持久化。redo log 写入关键将“将页 X 的 offset Y 改为 Z”记录到redo log buffer内存根据innodb_flush_log_at_trx_commit决定刷盘策略1默认每次事务提交调用fsync()强刷 redo log 到磁盘2写 OS Cache1 秒刷盘宕机可能丢 1 秒数据0每秒刷盘高性能高风险。undo log 暂不刷盘随脏页后台刷盘。性能核心innodb_flush_log_at_trx_commit1保证 ACID但每次提交触发磁盘 I/O1 次fsync≈ 1–10ms高并发下redo log 刷盘是主要瓶颈。阶段 4事务提交COMMIT1原子提交协议两阶段提交2PCPrepare 阶段将事务状态设为PREPARED强制刷 redo log 到磁盘fsync此时崩溃重启后可回滚或提交见恢复机制。Commit 阶段写binlog若开启用于主从复制将事务状态设为COMMITTED释放所有行锁将事务从活跃列表移除。⚠️崩溃安全若在 Prepare 后、Commit 前崩溃 → 重启时通过 redo log binlog自动提交若在 Prepare 前崩溃 → 重启时回滚。2提交后行为脏页不立即刷盘由后台线程Page Cleaner异步刷undo log 标记为可 purge由 purge 线程后台清理。阶段 5事务清理锁释放所有行锁、表锁释放MVCC 可见性更新新事务可看到此修改undo log 回收当无活跃事务需此版本purge 线程删除。二、关键组件交互图----------------- --------------------- ------------------ | SQL Layer | | InnoDB Storage | | Disk Subsystem | | (Parser, Optimizer)| | (Lock, Buffer Pool, | | (Redo Log, Data)| ----------------- | Undo/Redo, MVCC) | ------------------ | -------------------- ^ | | | | 1. 执行计划 | 2. 加锁、查数据 | |-----------------------| | | | 3. 写 undo log (内存) | | | 4. 修改脏页 (内存) | | | 5. 写 redo log buffer | | |------------------------| | | 6. COMMIT: fsync redo | |-----------------------| 7. 释放锁、移出活跃列表 | ----------------- --------------------- ------------------三、可验证实验1.观察锁行为-- 会话1STARTTRANSACTION;UPDATEusersSETnameAWHEREid1;-- 未 commit-- 会话2UPDATEusersSETnameBWHEREid1;-- 阻塞等待 X 锁释放2.验证 redo log 刷盘# my.cnf innodb_flush_log_at_trx_commit 1 # 安全 # innodb_flush_log_at_trx_commit 2 # 性能用iostat -x 1监控磁盘awaittrx_commit1时每次提交有 I/O spike。3.崩溃恢复测试启动事务 → 执行 UPDATE → kill -9 mysqld重启后数据要么全回滚要么全提交无中间状态。四、性能与调优杠杆点瓶颈优化方案风险redo log 刷盘慢RAID 10 SSD增大innodb_log_file_size配置不当导致恢复时间长锁竞争避免大事务用SELECT ... FOR UPDATE显式控制死锁风险undo log 膨胀监控Innodb_history_list_length调大innodb_purge_threads回滚段占内存binlog redo 2PC 开销组提交Group Commit自动优化无需手动干预五、常见误区❌ “COMMIT 后数据立即写磁盘” → 实际脏页异步刷盘但 redo log 已持久化❌ “事务越小越好” → 过小事务导致redo log 刷盘频率过高每条 SQL 一次fsync✅最佳实践事务包含完整业务单元如“扣库存创建订单”避免在事务中处理用户交互防止长持有锁。总结MySQL 事务执行链的核心是内存修改 redo log 原子持久化 锁/MVCC 隔离。ACID 的 A原子性靠 redo log 2PC 保证C一致性靠应用逻辑 约束I隔离性靠锁 MVCCD持久性靠fsyncredo log。理解这条链你就能在“慢事务”“死锁”“宕机恢复”问题中精准定位瓶颈而非盲目调参。