InnoDB:一条update语句执行过程

存储引擎InnoDB下执行一条update的语句要经过哪些步骤呢?假设我们执行如下SQL,本文宏观上将执行器和存储引擎视为一体(执行器和存储引擎交互)。

update user_info set name='岩枭' where id=1 and name='萧炎';

1、Buffer Pool

要执行更新操作,首先要拿到where条件里定位的数据。存储引擎会先在Buffer Pool里找一找有没有这条数据,有则开干,没有的话只能去磁盘读取,然后加载到Buffer Pool。

试想一下,现在磁盘上有一个user.txt文件(简化下only one row)保存了一条用户信息,需要把里面的用户信息修改一下,是不是也需要用程序先读到内存里,处理完再写回磁盘。在这个过程中,需要读取这个用户信息,就可以直接从内存里获取。

2、undo log

执行更新之前,先给undo log写条日志,记录一下原数据信息,万一程序处理异常,事务是需要回滚的,那就需要undo log将数据回滚到更新之前。

试想一想,现在要开始更新从user.txt里加载到内存的数据了,稳妥起见,是不是先打个日志,记录一下更新之前,原来的数据是什么。

3、脏数据

现在把Buffer Pool里的数据进行修改,将’萧炎’,改成’岩枭’,这就产生了所谓的脏数据,因为内存数据已经更新了,但是磁盘数据并未更新。

4、Redo Log

更新内存数据后,再给Redo Log写条日志,记录一下对数据进行了怎样的修改,这样当MySQL宕机后,还能从Redo Log里恢复。Redo Log也有自己的buffer,通常的配置是提交事务时,将Redo Log进行刷盘。

所以没有提交事务时,即使MySQL宕机了也没关系,因为数据都在内存里,客户端也会收到异常。提交事务之后,即使MySQL宕机了还是没关系,MySQL可以根据Redo Log将数据恢复回来。

5、binlog

归档日志,上述步骤完成后,会在binlog里记录一下逻辑日志,简单理解为对哪个数据页的哪条数据进行了怎样的修改。然后将binlog的相关信息写到Redo Log里并打一个commit标记,此次事务就完成了。

6、数据落盘

经过上述步骤后,MySQL服务器内部的IO线程会在某个时刻把内存的数据同步写回磁盘,这样磁盘数据就是最新的数据了。

总结:

其实MySQL也可以看成是一个应用(业务)系统,一条update语句对于MySQL而言就是处理一个业务,为了支持撤销,保证宕机后可恢复,这个应用系统做了很多保障工作。

猜你喜欢

转载自blog.csdn.net/weixin_43275277/article/details/127859984