MySQL——update语句执⾏流程
图1 update语句执⾏流程
1. 从 Buffer Pool(内存中) 中查看是否有这条数据,没有就从磁盘中加载到缓冲池,然后对这⾏记录加独占锁;
2. 把更新⾏记录的旧值写⼊ undo log(以便回滚);
3. 更新 Buffer Pool 中的数据(成脏数据);
4. 执⾏器把对数据的修改情况写⼊ redo log 中(内存中) ;
5. 准备提交事务时(prepare 阶段),按策略把 redo log 刷到 redo log ⽂件(磁盘中);
6. 执⾏器⽣成这次更新的 binlog,再按策略刷到 binlog ⽂件(磁盘中);
switch case用法详解7. 执⾏器调⽤引擎的提交事务接⼝,完成最终的事务提交。(此时会把本次更新对应的 binlog ⽂件名称和这次更新的 binlog ⽂件⾥的
位置,写⼊到 redo log ⽂件中,同时在 redo log ⽂件⾥写⼊⼀个 commit 标记)
8. 如果触发刷新脏页的操作,则将内存更新后的脏数据刷回磁盘。
图2 update语句执⾏流程框架图
angular9教程
1. ⾸先客户端通过 tcp/ip 发送⼀条 sql 语句到 server 层的 SQL interface;
2. SQL interface 接到该请求后,先对该条语句进⾏解析,验证权限是否匹配;
android 退出app3. 验证通过以后,分析器会对该语句分析,是否语法有错误等;
4. 接下来是优化器器⽣成相应的执⾏计划,选择最优的执⾏计划;
伊利轮播台5. 之后会是执⾏器根据执⾏计划执⾏这条语句。clipchamp下载
在这⼀步会去 open table,如果该 table 上有 MDL 则等待。
如果没有,则加在该表上加短暂的 MDL(S)。
(如果 opend_table 太⼤,表明 open_table_cache 太⼩。需要不停的去打开 frm ⽂件);
mysql语句顺序6. 进⼊到引擎层,⾸先会去 innodb_buffer_pool ⾥的 data dictionary (元数据信息) 得到表信息;
7. 通过元数据信息,去 lock info ⾥查出是否会有相关的锁信息,并把这条 update 语句需要的锁信息写⼊到 lock info ⾥(锁这⾥还有
待补充);
8. 然后涉及到的⽼数据通过快照的⽅式存储到 innodb_buffer_pool ⾥的 undo page ⾥,并且记录 undo log 修改的 redo(如果
data page ⾥有就直接载⼊到 undo page ⾥,如果没有,则需要去磁盘⾥取出相应 page 的数据,载⼊到 undo page ⾥);
9. 在 innodb_buffer_pool 的 data page 做 update 操作。并把操作的物理数据页修改记录到 redo log buffer ⾥,由于 update 这
个事务会涉及到多个页⾯的修改,所以 redo log buffer ⾥会记录多条页⾯的修改信息。因为 group commit 的原因,这次事务所产⽣的 redo log buffer 可能会跟随其它事务⼀同 flush 并且 sync 到磁盘上;
10. 同时修改的信息,会按照 event 的格式,记录到 binlog_cache 中。(这⾥注意 binlog_cache_size 是 transaction 级别的,不是
session 级别的参数,⼀旦 commit 之后,dump 线程会从 binlog_cache ⾥把 event 主动发送给 slave 的 I/O 线程);
11. 之后把这条 sql,需要在⼆级索引上做的修改,写⼊到 change buffer page,等到下次有其他 sql
需要读取该⼆级索引时,再去与
⼆级索引做 merge 。
(随机I/O变为顺序I/O,但是由于现在的磁盘都是SSD,所以对于寻址来说,随机I/O和顺序I/O差距不⼤);
12. 此时 update 语句已经完成,需要 commit 或者 rollback。这⾥讨论 commit 的情况;
13. commit 操作,由于存储引擎层与 server 层之间采⽤的是内部 XA (保证两个事务的⼀致性,这⾥主要保证 redo log 和 binlog 的原
⼦性),所以提交分为 prepare 阶段与 commit 阶段;
14. prepare 阶段,将事务的 xid 写⼊,将 binlog_cache ⾥的进⾏ flush 以及 sync 操作(⼤事务的话这步⾮常耗时);
15. commit 阶段,由于之前该事务产⽣的 redo log 已经 sync 到磁盘了。所以这步只是在 redo log ⾥标记 commit;
16. 当 binlog 和 redo log 都已经落盘以后,如果触发了刷新脏页的操作,先把该脏页复制到 doublewrite buffer ⾥,把 doublewrite
buffer ⾥的刷新到共享表空间,然后才是通过 page cleaner 线程把脏页写⼊到磁盘中。
其实在实现上5是调⽤了6的过程了的,所以是⼀回事。MySQL server 层和InnoDB层都保存了表结构,所以有书上描述时会拆开说。
参考资料
[1]《MySQL实战45讲》
[2] MySQL技术内幕 InnoDB存储引擎 第2版

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。