https://blog.csdn.net/weixin_51754274/article/details/137746382
1. Bin log
1.1 bin log 是什么:
binlog是MySQL数据库中的二进制日志(Binary Log)的简称。它是MySQL服务器用来记录对数据库进行的修改操作的一种日志文件。当对数据库进行了INSERT、UPDATE、DELETE等写操作时,MySQL会将这些操作以二进制的形式记录到binlog中,而不是记录对应的SQL语句。这个binlog文件可以用于数据恢复、主从复制、以及数据库的备份等操作。
1.2 bin log的三种日志格式:
binlog 有三种记录格式,分别是ROW、STATEMENT、MIXED。
1、ROW: 基于行的复制模式,基于变更的数据行进行记录,如果一个update语句修改一百行数据,那么这种模式下就会记录100行对应的记录日志。
2、STATEMENT(mysql默认的日志格式):基于语句的复制模式。基于SQL语句级别的记录日志,相对于ROW模式,STATEMENT模式下只会记录这个update 的语句。所以此模式下会非常节省日志空间,也避免着大量的IO操作。
3、MIXED: 混合模式,此模式是ROW模式和STATEMENT模式的混合体,一般的语句修改使用statment格式保存binlog,如一些函数的日志;对于statement无法完成主从复制的操作,则采用row格式保存binlog。
1.3 bin log的刷盘时机
binlog 写入策略在进行事务的过程中,首先会把binlog 写入到binlog cache中(因为写入到cache中会比较快,一个事务通常会有多个操作,避免每个操作都直接写磁盘导致性能降低),事务最终提交的时候再吧binlog 写入到磁盘中。当然事务在最终commit的时候binlog是否马上写入到磁盘中是由参数 sync_binlog 配置来决定的。
1、sync_binlog=0 的时候,表示每次提交事务binlog不会马上写入到磁盘,而是先写到page cache,相对于磁盘写入来说写page cache要快得多,不过在Mysql 崩溃的时候会有丢失日志的风险。
2、sync_binlog=1 的时候,表示每次提交事务都会执行 fsync 写入到磁盘(mysql默认的机制);
3、 sync_binlog的值大于1 的时候,表示每次提交事务都 先写到page cach,只有等到积累了N个事务之后才fsync 写入到磁盘,同样在此设置下Mysql 崩溃的时候会有丢失N个事务日志的风险。很显然三种模式下,sync_binlog=1 是强一致的选择,选择0或者N的情况下在极端情况下就会有丢失日志的风险,具体选择什么模式还是得看系统对于一致性的要求。
2. Redo log
2.1 redo log是什么
redo log是innodb引擎级别,用来记录innodb存储引擎的事务日志,不管事务是否提交都会记录下来,用于数据恢复。当数据库发生故障,innoDB存储引擎会使用redo log恢复到发生故障前的时刻,以此来保证数据的完整性。将参数innodb_flush_log_at_tx_commit设置为1,那么在执行commit时会将redo log同步写到磁盘。
redo log 的设计目标是支持innodb的“事务”的特性,事务ACID特性分别是原子性、一致性、隔离性、持久性, 一致性是事务的最终追求的目标,隔离性、原子性、持久性是达成一致性目标的手段,根据的文章我们已经知道隔离性是通过锁机制来实现的。 而事务的原子性和持久性则是分别通过undo log和redo log 来保障的。
2.2 redo log刷盘时机
- redo log占用的空间是一定的,并不会无线增大(可以通过参数设置),写入的时候是进顺序写的,所以写入的性能比较高。当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。
- 在写入redo log的时候也有一个redo log buffer,日志什么时候会刷到磁盘是通过innodb_flush_log_at_trx_commit 参数决定。
- innodb_flush_log_at_trx_commit=0 ,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中,只有当buffer中存储了多个事务日志才会刷入磁盘中;
- innodb_flush_log_at_trx_commit=1,表示每次事务提交时都将 redo log 直接持久化到磁盘;
- innodb_flush_log_at_trx_commit=2,表示每次事务提交时都只是把 redo log 写到 page cache(内核缓冲区)。
3. 除了上面几种机制外,还有其它两种情况会把redo log buffer中的日志刷到磁盘。
- 定时处理:有线程会定时(每隔 1 秒)把redo log buffer中的数据刷盘。
- 根据空间处理:redo log buffer 占用到了一定程度( innodb_log_buffer_size 设置的值一半)占,这个时候也会把redo log buffer中的数据刷盘。
3. Undo log
Undo log 以逻辑方式记录数据库事务的修改操作,它记录了事务执行过程中旧值的备份,以便在事务回滚或并发控制需要时能够恢复数据。
例如:当我们执行一条 insert 语句时,Undo Log 就会记录一条相反的 delete 语句。
3.1 Undo log 的作用:
-
事务回滚:在事务执行过程中,如果出现错误或需要回滚操作,Undo log 可以恢复事务执行之前的数据状态,实现事务的回滚操作。
- 并发控制:通过 Undo log 的使用,数据库可以实现并发事务的隔离性和一致性,避免数据读取和写入的冲突。
3.2 隐藏字段以及Undo Log版本链:
对于使用 InnoDB 存储引擎的表来说,它的聚簇索引记录中都包含两个必 要的隐藏列。
1、trx_id :每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的 事务id 赋值给 trx_id 隐藏列。
2、roll_pointer :每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到 undo日志 中,然 后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
insert undo只在事务回滚时起作用,当事务提交后,该类型的undo日志就没用了,它占用的Undo Log Segment也会被系统回收(也就是该undo日志占用的Undo页面链表要么被重用,要么被释放)。
假设 id = 100 的事务 A 插入一条行记录(id = 1, username = "Jack", age = 18),那么,这行记录的两个隐藏字段 trx_id = 100 和 roll_pointer指向一个空的 undo log,因为在这之前并没有事务操作 id = 1 的这行记录。如图所示:
然后,id = 200 的事务 B 修改了这条行记录,把 age 从 18 修改成了 20,于是,这条行记录的 trx_id就变成了 200,roll_pointer就指向事务 A 生成的 undo log :
接着,id = 300 的事务 C 再次修改了这条行记录,把 age 从 20 修改成了 30,如下图:
可以看到,每次修改行记录都会更新 trx_id 和 roll_pointer 这两个隐藏字段,之前的多个数据快照对应的 undo log 会通过 roll_pointer 指针串联起来,从而形成一个版本链。MVCC 这个机制,其实就是靠 update undo log 实现的。
3.3 在使用 Undo log 时,需要注意:
-
Undo log 的管理和清理:由于 Undo log 会占用存储空间,需要定期清理不再需要的 Undo log,以释放存储空间。
-
配置 Undo log 的大小:根据数据库的并发事务量和数据修改量,合理配置 Undo log 的大小,以确保足够的空间来存储 Undo log 信息。
-
定期备份 Undo log:为了避免数据丢失,定期备份 Undo log 文件,以便在需要恢复数据时使用。
4. bin log和redo log :
4.1 有什么区别?
- bin log会记录所有日志记录,包括InnoDB、MyISAM等存储引擎的日志;redo log只记录innoDB自身的事务日志。
- bin log主要用于数据库的 主从复制 以及数据恢复工作(比如恢复到数据库的某一个历史版本),redo log 主要用于发生故障后,让所有数据恢复到发生故障之前的状态
- bin log是逻辑日志,记录的是SQL语句;redo log是物理日志,记录的数据格式是 “在某个数据页上做了什么修改”。
- bin log的日志空间是二进制流式的缓冲区,写完一个缓冲区后,不会覆盖之前的内容,而是重开一个缓冲区,继续写入日志;而redo log的日志空间大小是固定的,通过循环写入的方式将日志写入磁盘,一旦没有空闲空间,则会采用覆盖的方式,覆盖的之前的内容
- bin log只在事务提交前被写入一次磁盘(MySQL 5.7.7之后版本的默认保存方式),一个事务只写一次;而对于redo log,在事务开始时会写入一次磁盘,提交redo log为prepare状态,事务提交后又会写入一次磁盘,提交redo log 为commit状态
4.2 bin log日志恢复和redo log日志恢复的区别
binlog(二进制日志)恢复和redo log(重做日志)恢复是数据库恢复机制中的两个不同方面,它们的主要区别在于目标和内容:
-
目标不同:
1.1 binlog恢复的主要目标是用于数据库的逻辑恢复和复制。通过分析binlog中记录的SQL语句,可以还原数据库中的数据和操作,以实现数据恢复、主从复制等目标。binlog是用于逻辑恢复和数据同步的工具。
1.2 redo log恢复的主要目标是用于数据库的物理恢复。redo log包含了InnoDB存储引擎中发生的物理更改(如页的修改),它的主要作用是在数据库发生崩溃或故障时,确保数据的一致性和完整性,以防止数据损坏。redo log是用于物理恢复的工具。 -
内容不同:
2.1 binlog内容:binlog记录的是实际执行的SQL语句,这些语句包括数据的插入、更新、删除,以及数据库结构的变更(DDL语句)。binlog中的内容是逻辑操作的记录。
2.2 redo log内容:redo log记录的是InnoDB存储引擎所执行的物理更改。这包括数据页的修改,而不是SQL语句本身。redo log中的内容是物理操作的记录。 -
使用场景不同:
3.1 binlog的使用场景:binlog主要用于实现数据库的逻辑备份和还原,以及主从复制。它适用于恢复到特定时间点、误操作恢复和数据复制等场景。
3.2 redo log的使用场景:redo log主要用于数据库的物理恢复。它用于保证在数据库崩溃或发生故障时,数据库可以恢复到崩溃前的状态,以确保数据的一致性和完整性。
总之,binlog和redo log在数据库中扮演着不同的角色。binlog主要用于逻辑恢复和复制,记录的是SQL语句的逻辑操作。而redo log主要用于物理恢复,记录的是InnoDB存储引擎的物理操作,以确保数据的一致性和持久性。这两者在数据库备份、恢复和复制方面起到了关键作用,但它们的内容和目标不同。
5. redo log 和 undo log的区别
- 目的不同:redo log主要是用于发生故障时的数据恢复操作,将数据恢复到故障发生前的状态,而undo log主要用于事务的回滚,将数据恢复为事务发生前的状态
- redo log 和 undo log 都是MySQL用于实现事务和保证数据一致性的机制,但它们的作用不同:
2.1 Redo Log(重做日志): 主要用于保证事务的持久性(Durability)。当事务执行时,首先会把修改记录到redo log中,然后再慢慢地更新到磁盘的数据页中。这样即使系统突然宕机,也可以通过redo log来恢复数据。在MySQL的InnoDB存储引擎中,redo log是固定大小的,采用循环写入的方式,可以保证在系统宕机的情况下,最近的一段时间内的修改都不会丢失。
2.2 Undo Log(回滚日志): 主要用于实现事务的原子性(Atomicity)和一致性(Consistency)。当事务需要回滚或者其他事务需要读取旧的数据版本时,就需要使用undo log。undo log记录了事务执行过程中对数据的修改,如果事务失败需要回滚,或者其他事务需要读取数据修改前的版本,就会使用undo log中的信息来还原数据。