MySQL 日志系统 redo log ,Undolog和 binlog 说明

Undolog

UndoLog也就是我们常说的回滚日志文件 主要用于事务中执行失败,进行回滚,以及MVCC中对于数据历史版本的查看。由引擎层的InnoDB引擎实现,是逻辑日志,记录数据修改被修改前的值,比如"把id=‘B’ 修改为id = ‘B2’ ,那么undo日志就会用来存放id ='B’的记录”。

 当一条数据需要更新前,会先把修改前的记录存储在undolog中,如果这个修改出现异常,则会使用undo日志来实现回滚操作,保证事务的一致性。当事务提交之后,undo log并不能立马被删除,而是会被放到待清理链表中,待判断没有事物用到该版本的信息时才可以清理相应undolog。它保存了事务发生之前的数据的一个版本,用于回滚,同时可以提供多版本并发控制下的读(MVCC)也即非锁定读。

Reaolog

Redolog是重做日志文件是记录数据修改之后的值,用于持久化到磁盘中。

Redolog包括两部分:

  • 是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;
  • 是磁盘上的重做日志文件(redo log file),该部分日志是持久的。

  由引擎层的InnoDB引擎实现,是物理日志,记录的是物理数据页修改的信息,比如“某个数据页上内容发生了哪些改动”。当一条数据需要更新时,InnoDB会先将数据更新,然后记录redoLog 在内存中,然后找个时间将redoLog的操作执行到磁盘上的文件上。 不管是否提交成功我都记录,你要是回滚了,那我连回滚的修改也记录。它确保了事务的持久性。
 

Binlog

Binlog由Mysql的Server层实现,是逻辑日志,记录的是sql语句的原始逻辑,比如"把id=‘B’ 修改为id = ‘B2’。

  Binlog会写入指定大小的物理文件中,是追加写入的,当前文件写满则会创建新的文件写入。

  产生:事务提交的时候,一次性将事务中的sql语句,按照一定的格式记录到binlog中。

  用于复制和恢复在主从复制中,从库利用主库上的binlog进行重播(执行日志中记录的修改逻辑),实现主从同步。业务数据不一致或者错了,用binlog恢复。
 

1 重做日志(redo log)

redo log又称重做日志文件,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。innodb 使用了WAL 技术(Write-Ahead Logging)即先写日志,再写磁盘。 这样可以保证数据的一致性,在实例和介质失败(media failure)时,redo log文件就能派上用场,如数据库掉电,InnoDB存储引擎会使用redo log恢复到掉电前的时刻,以此来保证数据的完整性。

每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文件,redo log 循环使用,如默认的ib_logfile0和ib_logfile1。大小由innodb_log_file_size 参数控制,默认是48M。 文件个数由 innodb_log_files_in_group 参数控制,默认是2个。 文件名由ib_logfile为前缀。

  • innodb_log_file_size:指定每个redo日志大小,默认值48MB
  • innodb_log_files_in_group:指定日志文件组中redo日志文件数量,默认为2
  • innodb_log_group_home_dir:指定日志文件组所在路劲,默认值./,指mysql的数据目录datadir
[  mysql]# pwd
/var/lib/mysql
[ mysql]# ll -lh|grep ib_logfile
-rw-r----- 1 root  root   48M Aug 21 13:32 ib_logfile0
-rw-r----- 1 root  root   48M Aug 20 03:13 ib_logfile1
[dave@www.cndba.cn  mysql]#


mysql> show variables like 'innodb_log%';
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| innodb_log_buffer_size      | 16777216 |
| innodb_log_checksums        | ON       |
| innodb_log_compressed_pages | ON       |
| innodb_log_file_size        | 50331648 |
| innodb_log_files_in_group   | 2        |
| innodb_log_group_home_dir   | ./       |
| innodb_log_write_ahead_size | 8192     |
+-----------------------------+----------+
7 rows in set (0.01 sec)

2 二进制日志(binlog)

在之前的博客,我们了解到MySQL 体系架构有2个层次,如下:

MySQL Server 层 和 InnoDB 引擎层 体系结构MySQL Server 层 和 InnoDB 引擎层 体系结构_Michaelwubo的博客-CSDN博客

  1. Server 层:主要做的是 MySQL 功能层面的事情;
  2. 引擎层: 负责存储相关的具体事宜。

redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(二进制日志)。

binlog记录了对MySQL数据库执行更改的所有操作,但是不包括SELECT和SHOW这类操作,如果想记录SELECT和SHOW操作,那只能使用查询日志—general_log[={0|1}] (1为启用)。

binlog 属于逻辑日志,是以二进制的形式记录的是这个语句的原始逻辑。从 5.1.8 版本开始,二进制日志 (binlog) 有 3 种不同的格式可选:Mixed,Statement,Row,默认格式是 Statement,而从5.7.7版本以上默认是ROW模式。

MySQL binlog日志格式 binlog_format

MySQL binlog日志格式 binlog_format -- cnDBA.cn_中国DBA社区

mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |
| log_bin_basename                | /var/lib/mysql/mysql-bin       |
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF                            |
| log_bin_use_v1_row_events       | OFF                            |
| sql_log_bin                     | ON                             |
+---------------------------------+--------------------------------+
6 rows in set (0.01 sec)

mysql> show variables like '%binlog%';
+--------------------------------------------+----------------------+
| Variable_name                              | Value                |
+--------------------------------------------+----------------------+
| binlog_cache_size                          | 32768                |
| binlog_checksum                            | CRC32                |
| binlog_direct_non_transactional_updates    | OFF                  |
| binlog_error_action                        | ABORT_SERVER         |
| binlog_format                              | MIXED                |
| binlog_group_commit_sync_delay             | 0                    |
| binlog_group_commit_sync_no_delay_count    | 0                    |
| binlog_gtid_simple_recovery                | ON                   |
| binlog_max_flush_queue_time                | 0                    |
| binlog_order_commits                       | ON                   |
| binlog_row_image                           | FULL                 |
| binlog_rows_query_log_events               | OFF                  |
| binlog_stmt_cache_size                     | 32768                |
| binlog_transaction_dependency_history_size | 25000                |
| binlog_transaction_dependency_tracking     | COMMIT_ORDER         |
| innodb_api_enable_binlog                   | OFF                  |
| innodb_locks_unsafe_for_binlog             | OFF                  |
| log_statements_unsafe_for_binlog           | ON                   |
| max_binlog_cache_size                      | 18446744073709547520 |
| max_binlog_size                            | 1073741824           |
| max_binlog_stmt_cache_size                 | 18446744073709547520 |
| sync_binlog                                | 1                    |
+--------------------------------------------+----------------------+
22 rows in set (0.00 sec)

mysql>

[ mysql]# ll -lh|grep mysql-bin
-rw-r----- 1 root  root   177 Oct 26  2019 mysql-bin.000001
-rw-r----- 1 root  root  1.1G Dec  8  2020 mysql-bin.000002
-rw-r----- 1 root  root  528M Aug 21 14:05 mysql-bin.000003
-rw-r----- 1 root  root    57 Dec  8  2020 mysql-bin.index
[ mysql]#

redo log与binlog的区别

  1. redo log是在InnoDB存储引擎层产生,而binlog是MySQL数据库的上层产生的,并且二进制日志不仅仅针对INNODB存储引擎,MySQL数据库中的任何存储引擎对于数据库的更改都会产生二进制日志。
  2. 两种日志记录的内容形式不同。MySQL的binlog是逻辑日志,其记录是对应的SQL语句。而innodb存储引擎层面的重做日志是物理日志,记录的是在某个数据页上做了什么修改。
  3. 两种日志与记录写入磁盘的时间点不同,二进制日志只在事务提交完成后进行一次写入。而innodb存储引擎的重做日志在事务进行中不断地被写入,并日志不是随事务提交的顺序进行写入的。
  4. 二进制日志仅在事务提交时记录,并且对于每一个事务,仅在事务提交时记录,并且对于每一个事务,仅包含对应事务的一个日志。而对于innodb存储引擎的重做日志,由于其记录是物理操作日志,因此每个事务对应多个日志条目,并且事务的重做日志写入是并发的,并非在事务提交时写入,其在文件中记录的顺序并非是事务开始的顺序。
  5. binlog不是循环使用,在写满或者重启之后,会生成新的binlog文件,redo log是循环使用。
  6. binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。
     

binlog有固定的格式:

  1. statement 格式的 binlog,最后会有 COMMIT
  2. row 格式的 binlog,最后会有一个 XID event

从MySQL 5.6.2开始,引入了 binlog_checksum参数,用来验证 binlog 内容的正确性。对于 binlog 日志由于磁盘原因,可能会在日志中间出错的情况,MySQL 可以通过校验 checksum 的结果来发现,保证了事务 binlog 的完整性。

3 redo log 和 binlog 的数据一致性:两阶段提交(2PC)

MySQL 使用两阶段提交主要解决 binlog 和 redo log 的数据一致性的问题。

redo log 和 binlog 都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

两阶段提交过程如下:

  1. InnoDB redo log 写盘,完成后InnoDB 事务进入 prepare 状态。
  2. 如果前面 prepare 成功,那么开始binlog 写盘,将事务日志持久化到 binlog,如果持久化成功,那么 InnoDB 事务则进入 commit 状态(在 redo log 里面写一个 commit 记录),事务操作完成。如果有大量长事务在执行,那么这里就可能出现binlog 写入的等待,导致事务无法及时提交而出现阻塞。

每个事务 binlog 的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,recovery 过程中,binlog 最后一个 XID event 之后的内容都应该被 purge。

在redo log 和 binlog 文件中有一个共同的数据字段:XID。崩溃恢复的时候,会按顺序扫描 redo log:

  1. 如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;
  2. 如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务,进行回滚。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值