MySQL的redo log和bin log及相关问题

MySQL的redo log和bin log

redo log

redo日志即是重做日志,用于存储事务对数据库操作的记录,当数据库发生崩溃重启时,可以通过该日志进行恢复。

MySQL 中,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到那条记录,然后再更新,整个过程IO成本、查找成本都很高。redo日志的出现正是为了解决这个问题的。

​ 执行更新操作时,MySQL使用的技术是WAL(wirte-Ahead logging)技术,它的关键点在于先写日志,再写磁盘。具体来说,InnoDB引擎会先把记录写到redo log里面,并更新内存,这个时候更新计算完成了。等适当的时候,一般是空闲时,即会将这个操作记录更新到磁盘里面。

​ redo日志是固定大小的,写入擦除的操作可以理解为是循环链表的操作,存在两个指针wirte poscheckpoint,用于指向文件内存的位置。wirte pos是当前记录的位置,一边写一边后移。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

wirte poscheckpoint中间的部分表示剩余内存, 当wirte pos追上 checkpoint, 表示redo日志内存已经满了。需要擦除记录后,才能执行新的操作。

​ redo log的存在使得数据库具有crash-safe能力,即如果Mysql 进程异常重启了,系统会自动去检查redo log,将未写入到Mysql的数据从redo log恢复到Mysql中去。

binlog日志

binlog日志又可以叫归档日志,属于Server层的日志,用于存储语句的逻辑(有三种格式)。

它可以用来查看数据库的变更历史、数据库增量备份和恢复、Mysql的复制(主从数据库的复制)。

binlog有三种格式:Statement、Row以及Mixed。

  • 基于SQL语句的复制(statement-based replication,SBR);
  • 基于行的复制(row-based replication,RBR);
  • 混合模式复制(mixed-based replication,MBR)。

redo log刷盘的时机

通常来讲,redo log刷盘的时机是在事务提交的commit阶段采取刷盘的,在此之前,redo log都存在于redo log buffer这块指定的内存区域中。

  • log buffer 空间不足时;

    ​ log buffer空间是有限的,通过系统变量innnodb_log_buffer_size大小决定;如果当前写入log buffer的redo 日志量已经占满了50%左右,就需要把这些日志刷新到磁盘中。

  • 事务提交时;

    为了保证持久性,必须要把页面修改时所对应的redo日志刷新到磁盘中;否则系统崩溃后,无法将该事务对页面所做的修改恢复过来。

  • 后台有一个线程,约每秒一次的频率将log buffer中的redo日志刷新到磁盘;

  • 正常关闭服务器时;

  • 做chekpoint操作时,即擦除不需要的redo日志时;

相关问题

1. 为什么会有两份日志呢

​ MySQL在5.5之前是没有InnoDB引擎的,默认引擎是MyISAMMyISAM 没有cash-safe的能力,即崩溃后重启恢复的能力,binlog日志只能用于归档。而InnoDB是另外一家公司以插件形式引入MySQL的,既然只依靠binlog日志是没有cash-safe 能力的,所以InnoDB使用了另外一套日志,即redo log日志去实现cash-safe能力。

2. redo日志和binlog日志的不同

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

3. 什么是两阶段提交?

​ 两阶段提交是MySQL执行更新操作时,针对relog的写入拆分了两个步骤:preparecommit。在存储引擎更新新数据到内存后,会将这个更新记录到redo log里面,此时redo log处于prepare阶段。然后告知执行器执行完成了,随时可以提交事务。接着执行器会生成这个操作的binlog,然后写入磁盘。执行器调用存储引擎事务的提交接口,存储引擎把刚刚写入的redo log日志改为commit状态,至此更新完成。

注意:当redo log状态为prepare时,需要查询对应的binlog事务是否成功,决定回滚还是执行。

两阶段提交的作用是为了保证redo log 和bin log日志数据的一致性。

假设redo log 和bin log日志分开写,当第二个日志没有写完期间发生了crash

参考资料:

丁奇《Mysql实战45讲》

小孩子4919 《MySQL是怎样运行的–从根儿理解MYSQL》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值