MySQL的update语句是如何执行的?
一、涉及到的组件及其作用
-
BufferPool: 在更新 MySQL 数据的时候,会先确定BufferPool中是否存在该数据。如果存在的话,直接更新BufferPool中的数据,MySQL会定时将脏页刷新到磁盘。如果不存在的话,会先读取磁盘上的数据到BufferPool中再进行操作。
-
UndoLog:回滚日志。在RR(可重复读)的隔离级别下,会开启MVCC(多版本并发控制)。个别版本的数据需要通过回滚日志得到。
-
RedoLog:redolog是InnoDB引擎中存储数据的文件,可用于MySQL数据库实例的崩溃恢复。与BinLog 配合在一起可保证在数据更新过程中的数据一致性。
-
BinLog:归档日志。是MySQL 的 Server 层记录的日志。除了在数据更新场景下与Redolog一起保证数据一致性之外,在主备场景下,master实例是通过向slave实例传输归档日志来同步数据的。
二、执行过程
一个数据库在使用 InnoDB 存储引擎情况下,执行一个 update
语句会经历以下步骤:
- 保证数据在BufferPool。如果该数据在BufferPool中存在,则进行下一步,若不存在,则将该数据读取到BufferPool(MySQL在读取数据时会将整页数据都读取到内存中)。
- 记录undoLog。MySQL的默认隔离级别是RR,这种情况下会记录回滚日志,方便其他事务在获取其他版本的数据的时候进行回滚。
- 更新BufferPool中的数据。不是直接更新磁盘上的数据。
- 更新Redolog。更新Redolog中的数据,将该事务的状态置为
Prepare
状态。 - 更新BinLog。更新Binlog中对应的数据。
- 更新RedoLog。更新RedoLog中该事务的状态为
COMMIT
,提交该事务。 - 将更新同步到磁盘。在BufferPool中已经被修改过的数据但是还没同步到磁盘上的数据页叫脏页。BufferPool中的脏页会被MySQL通过异步任务的方式定期同步到磁盘上。