【数据库/MySQL】MySQL三大日志提要

MySQL三大日志

mysql常用日志

  • 错误日志
  • 查询日志
  • 慢查询日志
  • 事务日志【redo log(重做日志)、undo log(回滚日志)】
  • 二进制日志【bin log】

MySQL日志中比较重要的包括redo log(重做日志)、binlog(归档日志)和undo log(回滚日志)。

redo log

The most crucial structure for recovery operations is the redo log, which consists of two or more preallocated files that store all changes made to the database as they occur. Every instance of an Oracle Database has an associated redo log to protect the database in case of an instance failure.

恢复操作的最关键结构是重做日志,该日志由两个或多个预关注的文件组成,这些文件存储在数据库中进行的所有更改。Oracle数据库的每个实例都有关联的重做日志,以保护实例失败的情况。

**redo log是物理日志,属于InnoDB存储引擎。**为了应对InnoDB各种各样不同的需求,到MySQL 8.0为止,已经有多达65种的REDO记录。用来记录这不同的信息,恢复时需要判断不同的REDO类型,来做对应的解析。根据REDO记录不同的作用对象,可以将这65中REDO划分为三个大类:作用于Page,作用于Space以及提供额外信息的Logic类型。

对于MySQL数据库,redo log是InnoDB存储引擎独有的,提供了崩溃恢复能力。MySQL 实例挂了或宕机了,重启时InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。

MySQL中数据以页为单位,查询记录加载出来的数据叫数据页,会放入到Buffer pool中。后续查询先从Buffer Pool中找,没有命中再到硬盘中加载,减少硬盘IO开销。

更新表数据的时候,也是如此,发现 Buffer Pool 里存在要更新的数据,就直接在 Buffer Pool 里更新。

然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到 redo log 文件里。

刷盘时机

InnoDB 存储引擎为 redo log 的刷盘策略提供了 innodb_flush_log_at_trx_commit 参数,它支持三种策略:

  • 0 :设置为 0 的时候,表示每次事务提交时不进行刷盘操作。

    0时,如果MySQL挂了或宕机可能会有1秒数据的丢失。

  • 1 :设置为 1 的时候,表示每次事务提交时都将进行刷盘操作(默认值)

    1时, 只要事务提交成功,redo log记录就一定在硬盘里,不会有任何数据丢失。

    如果事务执行期间MySQL挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损失。

  • 2 :设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache

    2时, 只要事务提交成功,redo log buffer中的内容只写入文件系统缓存(page cache)。

    如果仅仅只是MySQL挂了不会有任何数据丢失,但是宕机可能会有1秒数据的丢失。

innodb_flush_log_at_trx_commit 参数默认为 1 ,也就是说当事务提交时会调用 fsync 对 redo log 进行刷盘。

另外,InnoDB 存储引擎有一个后台线程,每隔1 秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用 fsync 刷盘。

"挂了"和“宕机”:认为挂了是运行异常,应该还会把cache的存储进行刷盘;宕机可能是断电等,导致cache失效,存储丢失。

日志文件组

环形数组形式,从头开始写,写到末尾又回到头循环写。

为什么不直接刷盘

数据页大小是16KB,刷盘比较耗时,可能就修改了数据页里的几 Byte 数据,没有必要把完整的数据页刷盘。

数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。

所以用 redo log 形式记录修改内容,性能会远远超过刷数据页的方式,这也让数据库的并发能力更强。

bin log

bin log是逻辑日志,记录内容是语句的原始逻辑,属于MySQL Server层。不管用什么存储引擎,发生数据更新都会产生bin log日志。

MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

记录格式

  • statement:指定statement,记录的内容是sql语句原文

  • row:遇到例如update_time=now()这样会获取当前系统时间的类似情况,直接执行会导致与原库的数据不一致。指定为row,记录的内容就不再是简单的sql语句了,包含具体数据。row格式记录的内容看不到详细信息,要通过mysqlbinlog工具解析。通常情况下都是指定为row,这样可以为数据库的恢复与同步带来更好的可靠性。

  • mixed:row这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗IO资源,影响执行速度。

    所以就有了一种折中的方案,指定为mixed,记录的内容是前两者的混合。

    MySQL会判断这条SQL语句是否可能引起数据不一致,如果是,就用row格式,否则就用statement格式。

写入机制

事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache

write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快。

fsync,才是将数据持久化到磁盘的操作。

writefsync的时机,可以由参数sync_binlog控制,默认是0。

  • 0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync。但是机器宕机,page cache里面的 binlog 会丢失。
  • 为了安全起见,可以设置为1,表示每次提交事务都会执行fsync,就如同 redo log 日志刷盘流程 一样。
  • 折中方式,可以设置为N(N>1),表示每次提交事务都write,但累积N个事务后才fsync

两阶段提交

redo log(重做日志)让InnoDB存储引擎拥有了崩溃恢复能力。

binlog(归档日志)保证了MySQL集群架构的数据一致性。

两份日志可能逻辑不一致,导致恢复数据错误。为解决这一问题,InnoDB存储引擎使用两阶段提交方案,将redo log的写入拆成两个步骤,prepare和commit,两阶段提交。

undo log

概念:回滚日志,用来记录数据被修改前的信息。正好跟前面的重做日志进行相反操作。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。

作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读;

内容:逻辑格式的日志,在执行 undo 的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于 redo log 的。

另外,MVCC 的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB 通过数据行的 DB_TRX_IDRead View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改。

总结

主体主要参考自Javaguide对应章节

Javaguide中的总结:

MySQL InnoDB 引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性

MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值