欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > MySQL 修改数据的全链路流程

MySQL 修改数据的全链路流程

2025/6/6 21:37:54 来源:https://blog.csdn.net/Qzibidog/article/details/147932603  浏览:    关键词:MySQL 修改数据的全链路流程

MySQL 修改数据的全链路流程(InnoDB)

  • 全链路流程图
  • 关键步骤详解
    • 1. 建立连接阶段
    • 2.SQL解析与优化
    • 3. InnoDB内存操作
    • 4. 日志记录过程
    • 5. 二阶段提交(2PC)
  • 磁盘同步机制
    • 1. Redo Log刷盘策略(innodb_flush_log_at_trx_commit)
    • 2. Binlog刷盘策略(sync_binlog)
    • 3. 脏页刷新机制
  • 异常恢复流程
  • 性能优化要点
    • 1. 日志相关参数
    • 2.监控指标
  • 全链路耗时分布(示例)

全链路流程图

Client Connector BufferPool UndoLog RedoLog Binlog Disk 建立TCP连接 线程身份验证 发送UPDATE语句 检查数据页是否在内存 从磁盘加载数据页 返回数据页 alt [数据页不在内存] 记录修改前值(回滚日志) 修改内存数据页 记录物理变更(重做日志) prepare状态 记录逻辑变更 发送ack commit状态 返回执行成功 异步刷脏页 循环写日志文件 同步到磁盘 loop [后台线程处理] Client Connector BufferPool UndoLog RedoLog Binlog Disk

在这里插入图片描述

关键步骤详解

1. 建立连接阶段

查看当前连接

SHOW PROCESSLIST;
  • TCP三次握手建立连接
  • 线程验证(用户名/密码/IP白名单)
  • 连接池分配线程ID

2.SQL解析与优化

– 查看执行计划

EXPLAIN UPDATE users SET balance=100 WHERE id=5;
  • 语法解析器生成解析树
  • 优化器选择执行计划(是否走索引)

3. InnoDB内存操作

// 伪代码:Buffer Pool处理
if (!page_in_buffer_pool) {read_page_from_disk();
}row = find_row_in_page();
old_data = copy_row(row);  // 用于undo log
modify_row(row);           // 内存修改

4. 日志记录过程

日志类型内容示例写入时机
Undo Log把id=5的balance从200改为100修改前记录
Redo Logpage_no=3, offset=128, value=100prepare阶段
BinlogUPDATE users SET balance=100 WHERE id=5事务提交前

5. 二阶段提交(2PC)

客户端提交
Redo Log prepare
Binlog写入
Redo Log commit

磁盘同步机制

为什么Mysql不能直接更新磁盘上的数据而且设置这么一套复杂的机制来执行SQL了?
因为来一个请求就直接对磁盘文件进行随机读写,然后更新磁盘文件里的数据性能可能相当差。
因为磁盘随机读写的性能是非常差的,所以直接更新磁盘文件是不能让数据库抗住很高并发的。
Mysql这套机制看起来复杂,但它可以保证每个更新请求都是更新内存BufferPool,然后顺序写日志文件,同时还能保证各种异常情况下的数据一致性。
更新内存的性能是极高的,然后顺序写磁盘上的日志文件的性能也是非常高的,要远高于随机读写磁盘文件。
正是通过这套机制,才能让我们的MySQL数据库在较高配置的机器上每秒可以抗下几干甚至上万的读写请求

1. Redo Log刷盘策略(innodb_flush_log_at_trx_commit)

# my.cnf配置
innodb_flush_log_at_trx_commit=1  # 最安全(每次提交刷盘)

2. Binlog刷盘策略(sync_binlog)

sync_binlog=1  # 每次提交同步到磁盘

3. 脏页刷新机制

-- 查看刷页状态
SHOW ENGINE INNODB STATUS\G
  • 当脏页比例超过innodb_max_dirty_pages_pct(默认75%)时触发
  • 使用双写缓冲(Double Write Buffer)防止页断裂

异常恢复流程

graph TDA[MySQL启动] --> B{发现异常关闭标志?}B -->|是| C[进入崩溃恢复模式]B -->|否| Z[正常启动流程]C --> D[重做阶段 Redo Phase]D --> D1[从最后一个检查点LSN开始]D1 --> D2[扫描redo log文件]D2 --> D3[应用所有有效的redo记录]D3 --> D4[更新Buffer Pool中的脏页]D --> E[检查二阶段提交状态]E --> E1{Redo处于prepare状态?}E1 --是--> F[检查对应binlog]E1 --否--> G[事务已提交,跳过]   F --> F1{Binlog完整存在?}F1 -->|是| H[提交事务 XA COMMIT]F1 -->|否| I[回滚事务 XA ROLLBACK]H & I --> J[回滚阶段 Undo Phase]J --> J1[扫描undo log]J1 --> J2[回滚所有未提交事务]J2 --> J3[释放相关锁资源]J --> K[清理阶段 Purge Phase]K --> K1[清理无效undo日志]K1 --> K2[删除无用的历史版本]K2 --> K3[更新数据字典]K --> L[完成恢复]L --> M[服务可用]

在这里插入图片描述

性能优化要点

1. 日志相关参数

innodb_log_file_size=4G        # 更大的redo log文件
innodb_log_buffer_size=256M    # 增大日志缓冲区
binlog_group_commit_sync_delay=100  # 延迟组提交(微秒)

2.监控指标

-- 查看日志写入情况
SELECT * FROM performance_schema.innodb_metrics 
WHERE NAME LIKE '%log%';-- 查看脏页比例
SELECT (SELECT variable_value FROM information_schema.global_status 
WHERE variable_name='Innodb_buffer_pool_pages_dirty') / 
(SELECT variable_value FROM information_schema.global_status 
WHERE variable_name='Innodb_buffer_pool_pages_total') AS dirty_ratio;

全链路耗时分布(示例)

阶段典型耗时可优化手段
网络连接1-10ms使用连接池
SQL解析0.1-1ms避免复杂SQL
内存查找0.01-0.1ms增大Buffer Pool
日志写入0.5-5ms调整刷盘策略
磁盘同步1-10ms使用SSD

这个流程完整展示了从客户端发起到数据落盘的全过程,其中Redo Log的二阶段提交机制和WAL(Write-Ahead Logging)原则是保证ACID特性的关键设计。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词