前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL(二)日志系统

MySQL(二)日志系统

作者头像
JNJYan
发布2019-03-04 17:25:48
5410
发布2019-03-04 17:25:48
举报

更新语句的执行流程

MySQL可以恢复到半个月内任意一秒的状态. mysql> create table T(ID int primary key, c int);

这个表有一个主键ID和一个整型字段c,若要将ID=2这一行的值加1

mysql> update T set c=c+1 where ID=2;

首先执行语句前连接器要连接数据库,随后一个表上有更新时,跟这个表有关的查询缓存会失效,所以将表T上所有缓存结果都清空.分析器通过词法和语法解析直到这是一条更新语句,优化器决定使用ID这个索引,执行器负责具体执行,找到这一行,然后更新.

与查询流程不一样,更新流程还涉及两个重要的日志模块:redo log(重做日志)binlog(归档日志).

redo log

若每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程IO成本、查找成本都很高.

WAL(Write-Ahead Logging)技术即先写日志,再些磁盘. 当有一条记录需要更新时,InnoDB引擎就会将记录先写到redo log并更新内存,此时更新就算完成了,同时引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做.

InnoDB的redo log的大小是固定的,比如可以配置为一组4个文件,每个文件的大小是1GB,则共可以记录4GB的操作,从头开始写,写到末尾又回到开头循环写

write pos是当前记录的位置,一边写一边后移,checkpoint是当前要擦除的位置,也是往后推移并循环的,擦除记录前要将记录更新到数据文件.

write pos追上checkpoint则不能执行新的更新,要先擦掉一些记录,将checkpoint推进一下.

InnoDB通过redo log可以保证即使数据库发生异常重启,之前提交的记录也不会丢失,称为crash-safe.

binlog

redo log是InnoDB引擎特有的日志,而Server层也有自己的日志,称为binlog.

两者有如下不同:

  1. redo log是InnoDB引擎特有的,binlog是MySQl的Server层实现的,所有引擎都可以使用.
  2. redo log是物理日志,记录的是在某个数据页上做了什么修改,而binlog是逻辑日志,记录的是语句的原始逻辑,如’给ID=2行的c字段加1’.
  3. redo log是循环写的,空间固定会用完,binlog是可以追加写入的,追加写是指binlog文件写到一定大小后会切换值下一个,并不会覆盖以前的日志.

执行器和InnoDB引擎update语句的内部流程

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

redo log的写入拆成了两个步骤,preparecommit,即两阶段提交.

如何将数据库恢复至半个月内任意一秒的状态 binlog会记录所有逻辑操作,并且采用追加写的形式,如果DBA承诺半个月内可以恢复,则备份系统中一定会保存最近半个月的所有binlog,同时系统会定期做整库备份.

当需要恢复到指定的某一秒时,可以这样做:

  • 首先,找到最近的一次全量备份,若运气足够好,可能就是昨天的一个备份,从这个备份恢复到临时库.
  • 然后从备份的时间点开始,将备份的binlog依次取出来,重放到中午误删表的那个时刻.

这样临时库和误删之前的线上库一样了,然后可以将表数据从临时库取出来,按需恢复到线上库.

两阶段提交

为了让两份日志之间的逻辑一致.

由于redo logbinlog是两个独立的逻辑,若不用两阶段提交,要么就是先写完redo log再写binlog,或采用反过来的顺序.

假设当前ID=2的行,字段c的值是0,再假设执行update语句过程中,在写完第一个日志后,第二个日志还没有写完期间就发生了crash.

  1. 先写redo log 再写binlog

假设redo log写完,binlog还没有写完时,MySQL进程异常重启,根据redo log,即使系统崩溃,仍然可以将数据恢复过来,所以恢复后c的值为1.

但是由于binlog没写完就crash了,这时候binlog里面就没有记录这个语句,因此之后备份日志的时候,存起来的binlog里面就没有这条语句.

如果用binlog来恢复临时库的话,恢复出来的库与原库的值不同.

  1. 先写binlog后写redo log

如果再binlog写完之后crash,由于redo log还没写,崩溃恢复以后这个事务无效,所以这一行的值为0,但binlog里已经记录了将c从0改为1,若用binlog恢复临时库,与原库值不同.

redo logbinlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年02月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 更新语句的执行流程
  • redo log
  • binlog
    • 执行器和InnoDB引擎update语句的内部流程
      • 两阶段提交
      相关产品与服务
      云数据库 SQL Server
      腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档