SQL更新语句执行过程及其缓存备份实现

首先SQL更新在词法语法解析和优化其实和查询语句是相似的,都是通过连接器连接,分析器解析,优化器优化,最后通过执行器调用Inndb存储引擎查询数据然后更新数据。而在执行操作语言时,会与查询语言不同。

清空缓存

如果MySQL数据库开启了缓存功能,那么,查询语句会根据表名去清空该表所有的缓存,在更新等操作语句较多的情况下,不开启缓存可能会有更高的性能。

SQL更新语句执行过程及其缓存备份实现

操作日志

MySQL操作日志有多种,操作语句会先操作数据,然后将操作存储到日志,包括redo log(重做日志)、undo log(提供回滚和多个行版本控制mvcc)【redo log和undo log都是inndb引擎实现的】以及binlog

整个过程如下,执行器先根据条件向存储引擎查询数据,拿到数据后进行修改,然后将数据在调用存储引擎插入行数据,然后进行如下的日志操作

redo log

redo log为物理日志,包括两部分:一是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;二是磁盘上的重做日志文件(redo log file),该部分日志是持久的。

redo log的日志文件具有固定大小,当存储达到上限时,就会进行刷盘处理,将部分历史操作删除,然后保存新的操作,正是因为有了redo log,才能保证MySQL宕机后数据不丢失,称之为crash-safe

redo log由存储引擎生成

undo log

在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

binlog(归档日志)

binlog由执行器生成

Redo log不是记录数据页“更新之后的状态”,而是记录这个页 “做了什么改动”。
Binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有。

update语句的内部流程

  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。
  2. 如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  3. 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  4. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  5. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

SQL更新语句执行过程及其缓存备份实现

总结

内容略浅,如果需要知道各个日志具体的执行策略,可以查询第二个连接的内容,讲述的比较清晰,更加深入。

link: 02 | 日志系统:一条SQL更新语句是如何执行的? (geekbang.org)

*link: 详细分析MySQL事务日志(redo log和undo log) - 骏马金龙 - 博客园 (cnblogs.com)

link: [玩转MySQL之四]MySQL缓存机制 - 知乎 (zhihu.com)

上一篇:【高级Java架构师系统学习】java培训班骗局


下一篇:MySQL45讲之IO性能提升