DB优化mysqlSQL

MYSQL语句执行大体流程

2019-10-18  本文已影响0人  NealLemon

学习笔记是学习了 极客时间 - 《MySQL实战45讲》整理的笔记。

MYSQL简单架构

MySQL 可以分为 Server 层和存储引擎层两部分。

MYSQL中 SQL语句的执行流程

查询语句执行流程如图:

msql查询.png

更新语句执行流程(InnoDB引擎)

InnoDB架构

InnoDB架构.png

在更新语句执行流程中,大部分会使用到内存池。

执行SQL语句

update T set c=c+1 where ID=2;
update.png

可以看到 更新语句执行的时候,涉及到了两个重要的日志模块。

WAL 技术

为什么会涉及这两个模块,首先我们需要了解一下 MYSQL WAL 技术,WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

relog1.png

write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。write pos checkpoint 之间的是用来记录新的操作。如果 write pos 追上 checkpoint,如要将数据写入磁盘后在进行下一步操作。

对比

redo log binlog
实现 InnoDB 引擎特有 Server 层所有引擎都可以使用。
类别 物理日志,记录的是“在某个数据页上做了什么修改” binlog 是逻辑日志,记录的是这个语句的原始逻辑。比如“给 ID=2 这一行的 c 字段加 1 ”。
写入方式 循环 追加,文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

两阶段提交( prepare 和commit

在之前的逻辑图中我们可以看到,进行了两阶段提交操作,为了让两份日志之间的逻辑一致。通过一种特殊的xid,可以在两阶段提交的不同时刻发生异常重启时,将redo和binlog联系起来。如下:

 [Note] Found 1 prepared transaction(s) in InnoDB
 [Note] commit xid 'MySQLXid\1\0\0\0\0\0\0\0\6\0\0\0\0\0\0\0'
非两阶段提交出现宕机问题 以update T set c=c+1 where ID=2;为例
  1. 先写 redo log 后写 binlog。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。
  2. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。

关于 binlog 和 redo log更为深入的了解 推荐阅读:一文带你看懂binlog和redo log

上一篇下一篇

猜你喜欢

热点阅读