前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redo log和binlog的一些好问题

redo log和binlog的一些好问题

作者头像
AsiaYe
发布2020-05-27 22:31:36
9460
发布2020-05-27 22:31:36
举报
文章被收录于专栏:DBA随笔DBA随笔

redo log和binlog的一些好问题

开始之前,放上之前画的一张关于update执行流程的图:

下面,我们结合这张图来看这些关于binlog和redo log的好问题。

01 两阶段提交的过程中发生崩溃

MySQL的两阶段提交能够保证binlog和redo log的一致性。

那么如果在两阶段提交的过程中,发生了数据库的崩溃,MySQL内部会做什么事情来保证数据的一致性呢?以上述的update操作为例:

a、当MySQL在新行记录写入redo log之前发生了崩溃,因为redo log还没有写入,内存中的更新会丢失,此时事务没有提交,所以MySQL再次重新启动之后,会将这个事务进行回滚。

b、当MySQL在新行记录写入了redo log之后,也就是时刻1发生了crash,那么redo log目前是prepare阶段,而binlog没有写入,此时MySQL同样会进行回滚。

c、当MySQL在新行记录写入了redo log之后,binlog也写入了,此时在时刻2发生crash,这个时候,因为MySQL在恢复的时候,会做如下两个判断动作:

1、如果redo log里面的事务是完整的,也就是已经有了commit标识,则直接提交;

2、如果redo log里面的事务只有完整的prepare,则判断对应的事务binlog是否存在并完整: a. 如果是,则提交事务; b. 否则,回滚事务。

02 MySQL如何判断binlog完整性?

如果binlog是statement模式的,最后面会出现一个commit的标识,如下:

代码语言:javascript
复制
use `test`/*!*/;
SET TIMESTAMP=1590418900/*!*/;
insert into test values (1,'zhangsan')
/*!*/;
# at 490
#200525 23:01:40 server id 2025725  end_log_pos 521 
COMMIT/*!*/;

如果binlog是row模式的,最后面会出现一个xid的event事件,如下:

代码语言:javascript
复制
### UPDATE `mysql`.`ha_health_check`
### WHERE
###   @1=1582266682672 /* LONGINT meta=0 nullable=1 is_null=0 */
###   @2='m' /* STRING(3) meta=65027 nullable=0 is_null=0 */
### SET
###   @1=1582266698557 /* LONGINT meta=0 nullable=1 is_null=0 */
###   @2='m' /* STRING(3) meta=65027 nullable=0 is_null=0 */
# at 790
#200221 14:31:38 server id 3141372998  end_log_pos 821 CRC32 0xf63b387d         Xid = 1289289427
COMMIT/*!*/;
# at 821
#200221 14:31:44 server id 3141372998  end_log_pos 886 CRC32 0xc01e5aea         GTID    last_committed=2   sequence_number=3

除此之外,MySQL5.6中还引入了binlog checksum的参数,用来确认binlog的正确性,一般情况下,这个参数在主从上的设置应该保持一致,要么都为none,要么都为CRC32

03 redo log和binlog是如何关联起来的?

redo log对于用户是不可见的,如果你强制用vim打开redo log,你会看到一堆乱码。在binlog中,我们可以看到binlog的xid值,这个值就是用来关联redo log和binlog的。

  • 如果碰到既有prepare、又有commit的redo log,就直接提交;
  • 如果碰到只有parepare、而没有commit的redo log,就拿着XID去binlog找对应的事务,能找到完整事务,则提交,找不到,则回滚。

04 为什么prepare、binlog写入之后事务需要提交?不能同时抛弃么?

其实对于主库来讲,redo log和binlog要么同时存在,要么同时回滚,都不影响redo log和binlog的一致性。之所以在redo log prepare阶段完成、binlog写入后让事务提交,本质上还是为了保证主库和从库的一致性。因为binlog一旦写入,会通过dump thread同步给从库,从库会应用这个binlog,那么如果主库上crash之后,将写入的binlog回滚了,就有可能造成主库和从库的数据不一致现象。

05 只用binlog或者redo log不能支持崩溃恢复么?

如果只有binlog,那么MySQL的执行逻辑将变成:

数据更新到内存---写binlog---提交事务.

这种情况下,如果写完binlog之后MySQL发生了crash,那么内存中的数据页是无法修复的,由于MySQL采用的是WAL技术,也就是先写内存日志再写磁盘,而binlog是没有能力恢复损坏的内存数据页的。

如果只有redo log,那么因为redo log是循环写的,也就没有办法保留很长的周期,失去了binlog归档变更操作的功能。再者主从复制的结构可能会更脆弱,高可用架构也就更谈不上了。

06 数据落盘是从redo log落盘的还是从buffer pool?

其实数据落盘和redo log是没有关系的,redo log本身不记录数据页的完整数据,它只记录数据也的物理变更。

数据的落盘其实是将buffer pool中的脏页刷新到磁盘的过程。所谓的脏页,就是buffer pool中被修改的和磁盘上不一致的数据页。

在MySQL崩溃回复的过程中,如果发现某个数据页可能在崩溃回复的过程中,丢失了更新,就会将这个数据页加载到内存,也就是buffer pool,让redo log更新内存中的内容。更新完成之后,这个数据页就变为脏页,可以刷新回磁盘了。

07 redo log buffer和redo log的写入顺序?

假设有这么一个事务:

begin;

insert xxx 1

insert xxx 2

commit;

在commit之前,需要保存这两个insert产生的redo log,但是又不能直接写入到redo log文件里面,此时这些redo log就先保存在redo log buffer里面,当我们执行commit的时候,才会把redo log写入到iblogfile里面。

所以写入顺序上来讲,redo log buffer先写入,而redo log文件后写入。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01 两阶段提交的过程中发生崩溃
  • 02 MySQL如何判断binlog完整性?
  • 03 redo log和binlog是如何关联起来的?
  • 04 为什么prepare、binlog写入之后事务需要提交?不能同时抛弃么?
  • 05 只用binlog或者redo log不能支持崩溃恢复么?
  • 06 数据落盘是从redo log落盘的还是从buffer pool?
  • 07 redo log buffer和redo log的写入顺序?
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档