redo log

redo log

redo log 用于记录事务操作的变化,记录的是sql语句执行之后数据页上的具体修改内容。

redo log是innodb引擎独有,redo log不是二进制日志

redo log基本概念

https://www.jianshu.com/p/126fbdef0e12

https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html

redo log包括两部分:内存中的日志缓冲redo log buffer、磁盘上的重做日志文件redo log file


基本操作流程

1、redo log就是存储了数据被修改后的值。当提交一个事务时,InnoDB会先把数据写入redo log 日志。

2、然后再去修改内存中buffer pool里面的真正数据页。

3、通过 checkpoint机制写入到 disk。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6gh5aYLH-1620885380246)(0E92C62B750C4BC5B800010102E97BB4)]

redo log buffer处于 用户空间 ,数据 需要先写到 内核空间的os buffer ,而os buffer中的数据 写入磁盘log files,需要进行系统调用(sync()操作)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gsWtAgj-1620885380248)(11EE057E18B3486E8C88114DC8C290CE)]

MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。该变量有3种值:0、1、2,默认为1。但注意,这个变量只是控制commit动作是否刷新log buffer到磁盘。

当设置为1的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
当设置为0的时候,事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。
参数innodb_log_buffer_size控制redo log buffer大小,默认16mb

日志块(log block)

innodb存储引擎中,redo log以块为单位进行存储的,每个块占512字节,称为redo log block。

log buffer、os buffer、redo log file on disk中,都是以512字节的块存储的。

每个redo log block由3部分组成:日志块头、日志块尾 和 日志主体。

其中日志块头占用12字节,日志块尾占用8字节,日志主体部分只有512-12-8=492字节。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKUC6zud-1620885380249)(0F299FAD8B9D4B3891F71E29F4CB695A)]


日志块头

日志块头包含4部分:

log_block_hdr_no:(4字节)该日志块在redo log buffer中的位置ID。
log_block_hdr_data_len:(2字节)该log block中已记录的log大小。写满该log block时为0x200,表示512字节。
log_block_first_rec_group:(2字节)该log block中第一个log的开始偏移位置。
lock_block_checkpoint_no:(4字节)写入检查点信息的位置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9XiFTeL7-1620885380251)(AC904FCC070A433D93F1F502DB7CB971)]


log body(redo log的格式)

log body的格式分为4部分:

redo_log_type:占用1个字节,表示redo log的日志类型。
space:表示表空间的ID,采用压缩的方式后,占用的空间可能小于4字节。
page_no:表示页的偏移量,同样是压缩过的。
redo_log_body表示每个重做日志的数据部分,恢复时会调用相应的函数进行解析。

例如insert语句和delete语句写入redo log的内容是不一样的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PoDF6LOq-1620885380252)(5058749DF7434AC785E8CC2F25D179DA)]


redo log group和redo log file

redo log group

redo log group(重做日志文件组),一个组内由多个大小完全相同的redo log file组成。组内redo log file的数量由变量 innodb_log_files_group 决定,默认值为2,即两个redo log file。

可以通过变量 innodb_log_group_home_dir 来定义组的目录,redo log file都放在这个目录下,默认是在datadir下。

在innodb将log buffer中的redo log block刷到这些log file中时,会以追加写入的方式循环轮训写入。
即先在第一个log file(即ib_logfile0)的尾部追加写,直到满了之后向第二个log file(即ib_logfile1)写。当第二个log file满了会清空一部分第一个log file继续写入。


redo log file

在每个组的第一个redo log file中,前2KB记录4个特定的部分,从2KB之后才开始记录log block。

除了第一个redo log file中会记录,log group中的其他log file不会记录这2KB,但是却会腾出这2KB的空间。如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jKJl8PGj-1620885380253)(82D67730E54A4527A0D71A0A1DE1FD0F)]

redo log file的大小对innodb的性能影响非常大,设置的太大,恢复的时候就会时间较长,设置的太小,就会导致在写redo log的时候循环切换redo log file。

日志文件参数:

SHOW VARIABLES LIKE 'innodb_log_file_size' -- 重做日志文件的大小。
SHOW VARIABLES LIKE 'innodb_log_files_in_group' -- 指定重做日志文件组中文件的数量,默认2
SHOW VARIABLES LIKE 'innodb_log_group_home_dir' -- innodb_log_group_home_dir

日志刷盘的规则

log buffer中未刷到磁盘的日志称为脏日志(dirty log)。

innodb有以下 刷日志到磁盘的规则:

1.发出commit动作时(默认)。
commit发出后是否刷日志由变量 innodb_flush_log_at_trx_commit 控制。

2.每秒刷一次。
由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。
要注意,这个刷日志频率和commit动作无关。

3.当log buffer中已经使用的内存超过一半时。

4.当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置。

数据页刷盘的规则

不仅仅是日志需要刷盘,脏数据页也一样需要刷盘

在innodb中,数据刷盘的规则只有一个:checkpoint。

checkpoint触发后,会将buffer中脏数据页和脏日志页都刷到磁盘。

innodb存储引擎中checkpoint分为两种:

sharp checkpoint:在重用redo log文件(例如切换日志文件)的时候,将所有已记录到redo log中对应的脏数据刷到磁盘。

fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:
    master thread checkpoint:由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。
    flush_lru_list checkpoint:从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。
    async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
    dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。

redo log作用

保证事务的持久性(数据恢复);

对数据进行修改时,是修改内存中的数数据,当内存中的数据当内存中数据还未刷回磁盘就宕机时,可以通过redolog恢复数据,而且redolog只是记录数据的修改,无需将完整的数据刷回磁盘;


redo log 和 bin log 的区别

redolog是物理日志,binlog是逻辑日志;  
redolog是innodb引擎的,binlog是 server层的;
redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。binlog 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上
redo log适用于崩溃恢复(crash-safe)。binlog适用于主从复制和数据恢复

binlog日志只用于归档,只依靠binlog是没有crash-safe能力的。但只有redo log也不行,因为redo log是InnoDB特有的,且日志上的记录落盘后会被覆盖掉。因此需要binlog和redo log二者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值