MySQL_01_数据更新的流程?底层如何执行?

更多精彩内容请关注


1、MySQL整体架构

MySQL_01_数据更新的流程?底层如何执行?

在执行到存储引擎这一步骤时,会根据具体的存储引擎,去磁盘获取数据。

2、InnoDB是如何执行Update语句?

下面只是讲解整个大流程,未涉及细节,细节会在后续陆续分享
MySQL_01_数据更新的流程?底层如何执行?

比如我们现在要执行 update users set name=‘小张’ where id=1

  1. 到存盘上找到需要更新的数据,比如数据为 id=1,name=小李,将数据放到缓存池中(Buffer Pool)

  2. 将查询出来的值( id=1,name=小李)写到undo日志文件中,目的是后期数据回滚,先将原来值记录下来,回滚的时候就从该日志中取出来,以后会相信分享undo日志详细内容

  3. 更新Buffer Pool中的值,改为name由小李-》小张

  4. 写到将更新操作记录一下,写到Redo log buffer(内存)中

  5. Redo log buffer中的数据持久化到磁盘Redo log文件中,这个时候就算是更新成功了,为什么要用Redo log,以及带来的好处,后续会分享,现在主要了解到整体的流程就行。

    这里有个参数可以设置,redo log持久化策略:innodb_flush_log_at_trx_commit,可配置为:0,1,2

    • 配置为0:提交事务的时候,不会持久化到redo日志文件中,这个时候宕机,会造成数据丢失

    • 配置为1:提交事务redo log从内存刷入到磁盘文件里去,只要事务提交成功,那么redo log就必然在磁盘里了

    • 配置为2:提交事务的时候,把redo日志写os cache缓存,而不是直接进入磁盘文件,可能1秒后再持久化到磁盘,和配置为0类似,会造成数据丢失。

  6. 写入binlog日志,binlog实际上是对哪个数据做了什么修改,和Redo log buffer类似,也是有刷盘策略:sync_binlog和innodb_flush_log_at_trx_commit类似

  7. 将binlog的记录写入到Redo日志中,为什么要做个标记呢?

    用来保持redo log日志与binlog日志一致的。必须是在redo log中写入最终的事务commit标记了,然后此时事务提交成功,而且redo log里有本次更新对应的日志,binlog里也有本次更新对应的日志 ,redo log和binlog完全是一致的,这个时候我们才认为是提交成功的

  8. 异步IO线程将修改后的数据刷到磁盘文件中

3、讨论下步骤2可能出现的问题

首先,步骤1,2,3,4中任何一步出问题,都不会有什么影响,因为所有的数据修改都是基于内存的,还没做持久化,数据库数据还是修改前的数据。

可能会出现问题是,写进redo log后MySQL宕机,这个时候,我们已经默认该数据修改成功,但是实际上,知识记录到redo log,并没有改到数据库里面正式的数据。MySQL的机制是,当MySQL宕机重启时,会去redo log中拿到之前放进的更新数据,再放到buffer pool中,这样又可以继续执行下面的步骤了,将更新后的数据刷到磁盘,不会造成数据不一致。