mysql日志

本文详细介绍了MySQL中的redo日志、undo日志和binlog日志,强调了它们在事务处理和数据恢复中的作用。redo日志记录物理修改,保证crash-safe;undo日志用于事务回滚;binlog日志作为逻辑日志,用于主从复制。文章还探讨了两阶段提交的重要性以及如何通过参数设置控制日志操作,并提及了组提交机制以优化磁盘I/O。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.总述

redo日志:innodb存储引擎的日志,物理记录,记录的是某个数据页做了哪些修改,记录的是数据修改之后的值,不管事务是否提交,都会记redo 日志。redo日志保持了事务的持久性。用于异常宕机,或者介质故障后的数据恢复。即有crash-safe的能力。

undo日志:用于记录事务开始前的状态,用于事务失败时的回滚数据。

binlog日志:归档日志,是 My SQL Server层的日志。属于逻辑日志,通过二进制的形式记录语句的原始状态。用于主从复制。

2.下面以一条更新语句来详细的说明执行流程:

表为:create table t(id int primary key, c int);

更新语句为:update t set c=c+1 where id=2;

指向流程如下图:

2.1 redo日志

前面总述中已经说了,redo日志记录了数据页做了哪些修改,那么,更新语句肯定是要记录redo log的。redo log的记录用到了WAL(Write-Ahead Logging)技术。

WAL的关键点就是先写日志,再写磁盘。具体来说,当有一条记录更新时,会先写入redo log,并更新内存。此时,更新就算完事了。之后,innodb引擎会在合适的时候,将这个操作记录更新到磁盘里。

innoDB的 redo log是固定大小的。比如配置为一组4个文件,每个文件大小为1g. 分别称为log-file0~3。其中,write pos标记了当前记录的位置,checkpoint标记了当前要擦除的位置。这2个标记位置都是往后推移并循环的。擦除记录前要把记录更新到数据文件。write pos和checkpoint之间的那部分空间,可以用来记录操作。如果write pos追上了checkpoint,说明redo log文件已写满了,这时候就不能再执行新的更新操作了,需要把checkpoint向前推进一下,即把redo log刷盘。

2.2 binlog日志

如上总述所及,binlog归档日志是属于Server层的。

2.3 redo VS binlog

1)redo log是inno DB引擎特有的;binlog是MySql的Server层实现的,所有引擎都可以使用;

2)redo log是物理日志,记录的是"在某个数据页上做了什么修改";binlog是逻辑日志,记录这个语句的原始逻辑,比如本文中的update操作:“给id=2这一行的c字段加1”;

3)redo log是循环写的,空间固定,且会用完;binlog是追加写的,binlog文件写到一定大小后会切换到下一个binlog文件,不会覆盖之前的日志。

2.4 下面针对这条update操作来看具体的执行流程:

1)执行器先找引擎获取到id=2这一行。 若id=2这行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要从磁盘读入内存中,再返回;

2)执行器拿到行数据,把该值加1,得到新的数据,再调用引擎接口写入这行新数据;

3)引擎将这行数据更新到内存中,同时将这个更新操作记录到redo log中,此时redo log处于prepare状态。

4)执行器生成这个操作的binlog,并把binlog写入磁盘。

5)执行器调用引擎的提交事务接口,将刚才写入的redo log状态改成commit状态,更新完成。

由上,redo log的写入会经过2种状态:prepare和commit状态。这就是“两阶段提交”。

2.5 两阶段提交

为什么要把redo log设计成两阶段提交呢?为了让两份日志 redo log和binlog这两份日志之间的逻辑一致。

假如没有两阶段提交,执行这条update语句的时候,在写完第一个日志后,第二个日志还没写就crash了。表里数据为(2,0)

1)先写redo log后写binlog

假设redo log写完后,binlog还没有写,mysql异常重启了。redo log可以恢复,即恢复后这行数据的值是1. 但是binlog没有,之后备份日志的时候,binlog日志里就没有这条更新语句,即如果用这个binlog复制从库时,恢复出来的这一行的数据c字段值就是0,和主库的不一致。

2)先写binglog,后写redo log

如果在写完binlog后发生了crash,redo log没有写入。那么崩溃恢复后这个事务是无效的,所以这行数据中c值还是0.但是binlog已经记录了"把c从0改成1".所以之后用这份binlog来复制从库时,复制出来的这一行的c字段值是1,和主库的不一致。

2.6 mysql参数控制redo log,bin log操作:

innodb_flush_log_at_trx_commit=1时,则每次事务的redo log都直接刷盘。建议设1,可以保证mysql异常重启后不丢数据。

sync_binlog=1,标识每次事务的binlog都刷盘,建议设1,可以保证mysql异常重启后binlog不丢失。

“双1配置”:即一个事务的完整commit前,需要经历2次刷盘,一次是redo log的prepare阶段,一次是binlog。

 

组提交机制:

如上,每个事务提交涉及2次写盘,如:mysql的tps每秒2万的话,根据上述的,每秒会写4万次盘,但是磁盘能力也就2万左右,怎么实际2万的tps?

解决方式就是组提交机制:

LSN: log sequence number,对应redo log的写入偏移量。递增。

若三个并发事务(对应的lsn分别为10,20,90)同时在prepare阶段,都写完redo log buffer了。则可以以组提交的方式,通过一次写盘(第一个事务写盘时,lsn为90,就会将Lsn90及之前的redo log buffer都刷盘,后两个事务也可以直接返回了),将这三个事务的redo log buffer都刷盘。

 

select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
update T set c=c+1 where ID=2
redo:write-ahead-logging 先写日志 再写磁盘  -wal

WAL机制减少磁盘写的原理:

1. redo log和binlog都是顺序写,比随机io快多了。

2.得益于组提交机制,减少写盘次数,降低磁盘的IOPS消耗。

redo log 固定大小  --innodb的日志  物理日志 记录 在某个数据页上做了什么修改 循环写 会用完  负责事务
binlog  server层的日志 归档日志    逻辑日志 记录语句的原始逻辑  追加写,不会覆盖之前的日志 负责归档 

rto(Recovery Time Objective) 一天一备 or 一周一备 衡量标准  binlog备份

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值