MySQL深度剖析之undo log & redo log & binlog专题(2021)

因为每次对磁盘随机读写影响性能,尤其是高并发的时候,所以引入了Buffer Pool, 即只要更新Buffer Pool中的记录,则算更新成功,那如果更新完了还没有flush到磁盘则宕机了,此时内存的这些修改后的记录就会丢失。所以引入了redo log,在写入内存的时候,同样写入到redo log。

如果在事务期间,需要执行多条SQL,如果更新某一条SQL失败,需要回滚,这时候前面的已经写入到内存了,怎么回滚呢? 所以引入了undo log, 在写入内存之前,记录修改数据之前的记录。

一 redo log

1.1 redo log 格式

MySQL记录修改后或者新增的数据,是直接把数据写入redo log吗?肯定不是,那么需要记录哪些内容呢?

#1 日志类型

#2 表空间ID(记录位于哪一个表空间,如果存在多个)

#3 数据页号(位于表空间中哪一个数据页)

#4 数据页中的偏移量

#5修改的数据的长度(可选,一般针对string类型,不知道修改了多少字节数据)

#6 具体修改的数据(修改的数据)

1.2 redo log buffer和redo log block

redo log是产生一条,写入一条到磁盘吗? 不是的,它是在数据库启动的时候,根据redo log buffer大小(innodb_log_file_size)分配内存空间,然后写入一个512字节大小日志块(redo log block), redo log block包括12字节的块头,496字节的body和4字节的尾部,如图所示:

如果redo log block写满了则在创建一个 redo log buffer继续写,当redo log buffer写满了则刷到磁盘。另外redo log block的header主要包括以下信息:

#1 block_no: 块号

#2 data_length: 当前写入了多少字节的数据

first_record_group: 一个事务可能有多个redo log, 一个事务就属于一个redo log分组,第一组redo log的偏移量

checkpoint_no: 检查点号

1.3 redo log buffer刷盘时机

#1 如果写入的redo log已经超过了redo log buffer的一半

#2 提交事务的时候会把redo log block写入磁盘

#3 有后台线程定时刷新

#4 MySQL实例停止

1.4 如果redo log file文件满了怎么办

redo log文件默认有2个文件,ib_logfile0和ib_logfile1,当ib_logfile0写满了则写入ib_logfile1,当ib_logfile1写满了则写入ib_logfile0,如此循环

二 undo log

2.1 undo log格式

2.2 undo log 回滚流程

#1 从undo log找到刚刚执行的操作

#2 如果是新增,则根据主键删除;如果是更新则根据id和旧值还原

三 binlog

binlog是归档日志,是MySQL服务器的通用日志,主要是记录的是偏逻辑性质的数据,而不是物理数据。在提交事务的时候,先把redo log刷盘之后,就把binlog cache刷盘,然后再确认对redo log的刷盘

3.1 binlog有哪些格式

3.1.1 statement

完全照搬执行的语句,不作任何压缩等,即SQL语句是什么,这里就记录什么,不会记录多余的元数据

优点:

#1 没有额外的信息,所以更加节省空间

#2 没有额外的信息,则在提交事务时候fsync刷盘的性能更好

缺点:

没有记录相对位置等元数据,很容易造成主从同步的时候主从不一致的情况,比如delete from test limit 10;时还会产生一个警告,大意就是使用statement格式时执行limit语句可能造成主从同步不一致。因为limit语句只是指定了删除10条记录,但没有指定具体是哪10条,当mysql在两次执行时选择了不同的索引进行操作时,删除的记录就是不同的。

3.1.2 row

对于DDL操作记录执行的SQL语句,但是对于DML语句则记录具体的数据行一般生产环境采用这种格式

优点:

可以屏蔽statement缺点,不会造成主从不一致

缺点:

#1 由于记录了每条数据的内容变更,导致了binlog日志占用了很大的空间,由于fsync时一次写入数据过多,在一定程度上影响了性能。

#2 另外,binlog 日志文件在写入日志的时候会被锁住,如果数据太多可能会导致性能问题。可以添加参数 binlog_row_image=minimal 来减少这个缺点

3.1.3 mixed

对于DDL,只记录SQL语句;对于DML,则根据判断是否有可能造成主从不一致,如果有可能则使用row这种格式,否则使用statement

优点:

相对节省空间,提高了性能;也可以避免主从同步不一致

3.2 binlog cache和临时文件

当执行增删改SQL语句时候,会为当前线程分配一块叫做binlog cache的内存块,用于缓存执行SQL语句产生的binlog event事件,大小由binlog_cache_size控制。如果binlog cache达到binlog_cache_size,则将binlog cache内容移到一个临时文件中保存,但是这个文件不能超过max_binlog_cache_size,如果超过则报错;客户端断开连接,binlog cache释放

3.3 binlog的刷盘时机和策略

binlog在事务提交的时候,且在redo log buffer里的数据刷到磁盘(prepare阶段),再将binlog刷入磁盘。

binlog的刷盘策略可以通过sync_binlog参数来控制:

sync_binlog = 0: 表示每次提交事务都只 write,不 fsync。即提交事务时候,将binlog写入磁盘并不是直接写入,而是写入操作系统缓存,即os cache中,当然如果这个时候宕机,os cache中的binlog会丢失

sync_binlog = 1: 表示每次提交事务都会执行 fsync。即此时会在提交事务的时候强制将binlog刷入磁盘文件,这样宕机了也不怕binlog丢失

sync_binlog = N: 表示累计N个事务后才会执行fsync,即刷入磁盘

四 redo log和binlog比较

#1 一个存储的是偏逻辑的日志;一个存储的是偏物理的日志

#2 binlog一般用于备份和同步;redo log一般用于数据重启恢复

#3 提交事务的时候一般是先写redo log,再写binlog

#4 binlog 和 redo log都有缓存,不同的是binlog是每一个线程或者事务都有自己的binlog cache,但是binlog 是共享缓存

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值