小米科技|一生挚友redo log、binlog《死磕MySQL系列 二》( 二 )


此处的一段时间必须视自己的业务情况而定 , 外界有用1分钟的日志量也有1小时的日志量来计算 。
首先看一下 MySQL客户端的一个命令 pager , 在 MySQL日常操作中 , 通过设置 pager的显示方式 , 可以大大提高工作效率 。
目前 , 要查看 sequence在一分钟之内的值 , 您就可以执行 pager grep sequence , 它对mysql> show engine innodb status\\ G select sleep (60); show engine innodbstatus\\ G;返回的结果 。
禁止 pager设置执行 nopager , 如果不执行该命令 , 则只有等到下一次重新启动该命令才会失效 。
此处咔咔是在虚拟机上做的操作 , 可以看到一分钟内是没有任何操作 , 所以值前后相同 , 你可以在测试服务器做测试 。
这样计算出来的select (后边数据-前面的数据)/1024/1024*60 asMB_per_hour;值是一个小时后 redo log的大小
但是用这种方法计算一定是不合适的 , 在一分钟内业务繁忙或者业务空闲时间计算出的值都会产生较大误差 。
合适的方法是在一天中确定几个时间点 , 用一个脚本定时执行 , 然后记录相应的值 , 再取平均值 , 计算出的误差将减至最小 。
【小米科技|一生挚友redo log、binlog《死磕MySQL系列 二》】什么是 sequece?当每个 binlog生成时 , 该值从1开始 , 然后递增 , 每增加一个事务 ,sequenumber就加上1 。
二、binlog您可以从总体上了解到 MySQL架构分为两层 , 一个是 server层 , 另一个是存储引擎层 。
server层当然是负责功能方面的 , 而存储引擎层则负责处理与存储相关的操作 。
而且上面提到的redo log是Innodb存储引擎层特有的 , 其它存储引擎是不具备的 , 而server层也有自己的日志记录 , 就是将要聊到的binlog 。
redo log和binlog的区别
redo log是Innodb引擎特有的 , 而binlog是MySQLserver层特有的 , 所有引擎都可以使用 。
redo log是物理日志 , 它记录的是一条更新操作所做的修改 , binlog是逻辑日志 , 记录的是一条更新语句执行逻辑
redo log是循环写的 , 并且空间是固定的 , 比如上面配置4个1GB的redo log文件 , binlog是追加写的 , 这个文件写完了 , 换下一个文件 , 不会覆盖以前的日志 。 这也就是你经常看到只要你有完整的binlog文件就可以给你恢复到你想要的数据 。
MySQL为什么会有俩份日志呢?
在没有Innodb存储引擎之前 , MySQL默认存储引擎是MyIsam , 但MyIsam是没有重启恢复能力的 , binlog日志也仅用于归档 。
Innodb是另一家公司以插件的形式引入到Mysql , 既然binlog没有重启恢复的能力 , 那么我就使用redo log来实现重启恢复的功能 。
这就导致了当你使用Innodb存储引擎时会写俩份日志 。
三、什么是两阶段提交对redo log、binlog有了一定的认识后再来看看一条更新语句的执行流程 。
update user set age = age + 1 where id = 1;

  • 执行器先到引擎层找到id = 1这一行 , 由于ID是主键 , 所以会在主键索引树找到这一行 。 如果ID=2这一行所在的数据页本来就在内存中 , 就直接返回给执行器 。 否则 , 需要先从磁盘中读入内存 , 然后再返回 。
  • 执行器拿到存储引擎返回id = 2结果后 , 给age加上1 , 原来是25 , 现在就是26在调用引擎接口写入这行新数据 。
  • 引擎将这行数据先更新到内存中 , 同时将这个更新操作记录到redo log中 , 此时redo log处于prepare状态 。 然后告知执行器执行完成了 , 随时可以提交事务 。
  • 接着执行器生成这个操作的binlog , 并把binlog写入磁盘 。
  • 执行器调用引擎的提交事务接口 , 引擎把刚刚写入的redo log改成提交commit状态 , 更新完成 。
到这里你应该就清晰了 , 一条更新SQL会先写redo log再写binlog , 这也就是标题为什么叫一生挚友redo log、binlog
四、为什么需要两阶段提交是为了让redo log跟binlog两份日志之间的逻辑一致 , 看下面俩种情况 。
先写redo log后写binlog
  • 更新语句为age = age +1
  • 将数据写入redo log , MySQL进程异常重启
  • 此时binlog还没有开始写
  • 系统重启后进行数据恢复此时的值为26