从一条更新SQL的执行过程窥探InnoDB之REDOLOG

1前言
数据库为了取得更好的读写性能 , InnoDB会将数据缓存在内存中(InnoDBBufferPool) , 对磁盘数据的修改也会落后于内存 , 这时如果进程或机器崩溃 , 会导致内存数据丢失 , 为了保证数据库本身的一致性和持久性 , InnoDB维护了REDOLOG 。 修改Page之前需要先将修改的内容记录到REDO中 , 并保证REDOLOG早于对应的Page落盘 , 也就是常说的WAL , WriteAheadLog 。 当故障发生导致内存数据丢失后 , InnoDB会在重启时 , 通过重放REDO , 将Page恢复到崩溃前的状态 。
2MYSQL更新语句的执行过程
2.1MYSQL的体系结构
大体来说 , MySQL可以分为客户端、Server层和存储引擎层三大部分 , 如图所示 。
Server层包括连接器、查询缓存、分析器、优化器、执行器等 , 涵盖MySQL的大多数核心服务功能 , 以及所有的内置函数(如日期、时间、数学和加密函数等) , 所有跨存储引擎的功能都在这一层实现 , 比如存储过程、触发器、视图等 。
存储引擎层负责数据的存储和提取 。 其架构模式是插件式的 , 支持InnoDB、MyISAM、Memory等多个存储引擎 。 现在最常用的存储引擎是InnoDB , 它从MySQL5.5.5版本开始成为了默认存储引擎 。
从一条更新SQL的执行过程窥探InnoDB之REDOLOG
文章图片
2.2更新SQL的执行
当我们执行一条更新SQL时是如何执行的呢 , 下面执行一条简单的SQL更新语句(默认存储引擎InnoDB)updateTsetc=c+1whereID=2;
第一步:连接器
先通过连接器连接到这个数据库上 。 连接器负责跟客户端建立连接、校验用户名密码的正确性,同时获取该用户的权限放到缓存中、维持和管理连接
第二步:缓存
连接建立完成后 , 如果执行的是SELECT查询语句会查询缓存中是否存在该SQL的结果集 , 如果存在结果则再校验用户表和数据的权限最终将查询到的结果返回 。 如果是UPDATE , DELETE等更新操作 , 那么跟这个表有关的查询缓存会置为失效 , 所以这条语句就会把表T上所有缓存结果都清空 。
第三步:分析器
如果没有命中查询缓存 , 就要开始真正执行语句了 。 首先 , MySQL需要知道你要做什么 , 因此需要对SQL语句做解析 。
分析器先会做“词法分析” 。 你输入的是由多个字符串和空格组成的一条SQL语句 , MySQL需要识别出里面的字符串分别是什么 , 代表什么 。 例如该语句中c列在表T中是否存在等 。
做完了这些识别以后 , 就要做“语法分析” 。 根据词法分析的结果 , 语法分析器会根据语法规则 , 判断你输入的这个SQL语句是否满足MySQL语法 。 该SQL语句中的update、where等是否符合SQL语法
第四步:优化器
经过了分析器 , MySQL就知道你要做什么了 。 在开始执行之前 , 还要先经过优化器的处理 。 优化器是在表里面有多个索引的时候 , 决定使用哪个索引;或者在一个语句有多表关联(join)的时候 , 决定各个表的连接顺序;优化器决定要使用ID这个索引 。 指定索引也就指定了后面的执行器需要调用存储引擎的哪个接口进行执行 。
第五步:执行器
MySQL通过分析器知道了你要做什么 , 通过优化器知道了该怎么做 , 于是就进入了执行器阶段 , 开始执行语句 。 开始执行的时候 , 要先判断一下你对这个表T有没有执行查询的权限 , 如果没有 , 就会返回没有权限的错误 。 执行器负责具体执行 , 找到这一行 , 然后更新 。
从一条更新SQL的执行过程窥探InnoDB之REDOLOG
文章图片
2.3InnoDB存储引擎引入REDOLOG
Mysql本身有自己的日志记录binlog(归档日志:分为row , statement两种模式) , 但是只依靠binlog是没有crash-safe能力的 , 所以在存储引擎层InnoDB使用另外一套日志系统redolog来实现crash-safe能力 。 同时为了取得更好的读写性能 , InnoDB会将数据缓存在内存中(InnoDBBufferPool) , 对磁盘数据的修改也会落后于内存 , 这时如果进程或机器崩溃 , 会导致内存数据丢失 , 从而保证数据库本身的一致性和持久性 。 修改Page之前需要先将修改的内容记录到REDO中 , 并保证REDOLOG早于对应的Page落盘 , 也就是常说的WAL , WriteAheadLog 。 当故障发生导致内存数据丢失后 , InnoDB会在重启时 , 通过重放REDO , 将Page恢复到崩溃前的状态 。