MySQL update 一条语句的过程
查询阶段
- 连接器:建立连接,校验用户身份
- 解析 SQL:通过解析器对 SQL 语句进行词法分析、语法分析,构建语法树。
- 执行 SQL:
- 预处理阶段:检查表或字段是否存在;将 * 扩展为表上的所有列。
- 优化阶段:优化器选择查询成本最小的执行计划;
- 执行阶段:根据执行计划执行 SQL 语句,获取记录并更新。
更新阶段
- 执行器调用存储引擎的接口,通过执行计划获取符合条件的记录:
- 如果记录所在数据页在 buffer pool 中,就直接返回给执行器更新;
- 如果记录不在 buffer pool,先将数据页从磁盘读入到 buffer pool,再返回记录给执行器。
- 执行器得到记录后,判断更新前后的记录是否一样:
- 如果一样就不进行后续流程;
- 不一样就把更新前的记录和更新后的记录都当作参数传给 InnoDB 层,让 InnoDB 执行更新记录的操作;
- 开启事务,更新记录前要先记录相应的 undo log,undo log 会写入 buffer pool 的 undo 页面,写入 undo 页面前需要先记录修改 undo 页面的 redo log。所以这里的流程是:先记录修改 undo 页面的 redo log ,然后再将 undo log 写入到 undo 页面。
- 写完 undo 页面后 InnoDB 开始更新记录,先将新的记录写到 redo log 里,再修改 buffer pool 中的记录,同时标记为脏页。InnoDB 会先将 redo log 写入到磁盘,再择机将脏页落盘(WAL 思想)。
- 至此,一条记录更新完了。
- 记录更新完后,会记录该语句对应的 binlog,事务提交会统一将该事务运行过程中所有 binlog 刷新到硬盘。
- 事务提交(两阶段提交):
- prepare 阶段:将 redo log 对应的事务状态设置为 prepare,然后将 redo log 刷新到硬盘。
- commit 阶段:将 binlog 刷新到磁盘,接着调用存储引擎的提交事务接口,将 redo log 设置为 commit。
- 至此,一条更新语句执行完成。
补充
redo log 刷盘时机
- redo log 不是直接写入到磁盘的,也是先写入到 redo log buffer(用户空间内存)中。
- redo log buffer 在 mysql 正常关闭时 | 每隔一秒 | redo log buffer 中记录写入量大于一半内存时会直接落盘。
- 事务提交时,可以通过参数控制是否直接落盘还是先写入到 redo log 文件(内核空间内存)中。
buffer pool 刷盘时机
脏页写入磁盘的操作与事务提交是解耦的。
- 后台线程定期刷盘;
- MySQL 正常关闭
- 手动刷新;
- Redo Log Buffer 满了;
- Buffer Pool 空间不足。
- 定期会触发 Checkpoint 操作,强制将一定数量的脏页刷盘,以减少系统崩溃时需要恢复的数据量。
binlog 刷盘时机
事务执行过程中会先把日志写到 binlog cache 中,事务提交时再把 binlog cache 写到 binlog 文件(内核空间内存)中。通过参数可以控制执行 fsync 的时机(从内核空间内存到磁盘)。
更多补充:MySQL 的 undo log,redo log,binlog 总结
原文地址:https://blog.csdn.net/qq_43710228/article/details/142435736
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!