具体更新一条记录 UPDATE t_user SET name = ‘xiaolin’ WHERE id = 1; 的流程如下:
-
执行器负责具体执行,会调用存储引擎的接口,通过主键索引树搜寻获取 id = 1 这一行记录:
- 如果 id=1 这一行所在的数据页原本就在 buffer pool 中,就间接返回给执行器更新;
- 如果记录不在 buffer pool,将数据页从磁盘读入到 buffer pool,返回记录给执行器。
-
执行器失去聚簇索引记录后,会看一下更新前的记录和更新后的记录是否一样:
- 如果一样的话就不进行后续更新流程;
- 如果不一样的话就把更新前的记录和更新后的记录都当作参数传给 InnoDB 层,让 InnoDB 真正的执行更新记录的操作;
- 开启事务,InnoDB 层更新记录前,首先要记录相应的 undo log,因为这是更新操作,须要把被更新的列的旧值记下来,也就是要生成一条 undo log,undo log 会写入 Buffer Pool 中的 Undo 页面,不过在内存批改该 Undo 页面后,须要记录对应的 redo log。
- InnoDB 层开始更新记录,会先更新内存(同时标记为脏页),而后将记录写到 redo log 外面,这个时候更新就算实现了。为了缩小磁盘 I /O,不会立刻将脏页写入磁盘,后续由后盾线程抉择一个适合的机会将脏页写入到磁盘。这就是 WAL 技术,MySQL 的写操作并不是立即写到磁盘上,而是先写 redo 日志,而后在适合的工夫再将批改的行数据写到磁盘上。
- 至此,一条记录更新完了。
- 在一条更新语句执行实现后,而后开始记录该语句对应的 binlog,此时记录的 binlog 会被保留到 binlog cache,并没有刷新到硬盘上的 binlog 文件,在事务提交时才会对立将该事务运行过程中的所有 binlog 刷新到硬盘。
-
事务提交,剩下的就是「两阶段提交」的事件了,接下来就讲这个。