更新语句的执行过程

 

更新语句的流程跟查询语句大体相同:
1.连接数据库 ——连接器的工作
2.在一个表上有更新的时候,跟这个表有关的查询缓存会失效
3.分析器会通过词法和语法解析知道这是一条更新语句
4.优化器决定要使用哪个索引(更新也需要先查找到目标行)
5.执行器负责具体执行,找到需要更新的行,然后更新。
 
 
与查询流程不一样的是,更新流程涉及两个重要日志模块:redo log(重做日志)和binlog(归档日志)。
 
其中redo log是innodb引擎独有的,而binlog是server层的日志,所以所有引擎都可以用。
【个人的记忆方法是认为bin是很多软件都自带的,所以对于binlog应该也是比较通用的,另外一个就是独特的】
 
【redo log】
WAL(Write-Ahead Logging)技术:关键点就是先写日志,再写磁盘。
 
当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。
同时,InnoDB引擎会在系统较空闲的时候将操作记录写入磁盘
 
redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么总共就可以记录4GB的操作,从头开始写,写到末尾就又回到开头循环写。
 
write pos 是当前记录的位置,一边写一边后移,写到第3 号文件末尾后就回到 0 号文件开头。
checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。
 
write pos 和 checkpoint 之间是还空着的部分,可以用来记录新的操作。
如果 write pos 追上 checkpoint,表示记录满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。
 
 
crash-safe:保证即使数据库发生异常重启,之前提交的记录都不会丢失
有了 redo log,InnoDB 就可以做到crash-safe

 

 

 

  【binlog】

为什么需要两份日志?因为单binlog没有crash-safe功能。所以innodb自己使用另一套——redolog
三点不同:
1.redo log 是 InnoDB 引擎特有的;binlog是 MySQL 的 Server 层实现的,所有引擎都可以使用
2.redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。(binlog的两种模式:1.记录sql语句,2.row:记录修改前后的数据记录)
3.redo log 是循环写的,空间固定会用完;binlog是可以追加写入的
 
 
【innodb引擎执行更新语句过程】

 

图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行

 

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

 

最后三步看上去有点“绕”,将 redo log 的写入拆成了两个步骤:prepare 和 commit,就是"两阶段提交"

 

本文摘自极客时间--丁奇的《Mysql45讲》,也向大家推荐这门课程

posted @ 2020-03-03 21:15  钺览IT  阅读(363)  评论(0编辑  收藏  举报