【MYSQL 三大常见日志】

MYSQL 三大常见日志

一、RedoLog日志

redo log也称为事务日志由InnoDB存储引擎层产生。记录的是数据库中每个页的修改,而不是某一行或某几行修改成怎样,可以用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置,因为修改会覆盖之前的)。
当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

1、写入策略

设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中 ;
设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘;
设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache。
InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。

2、刷盘时机

主要有下面几个时机:

  • MySQL 正常关闭时;
  • 当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;
  • InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。
  • 每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘(这个策略可由innodb_flush_log_at_trx_commit 参数控制)。

二、UndoLog日志

undo log用于回滚数据,在开始执行事务时,MySQL会把更新前的数据都记录到undolog里面,事务提交前如果MySQL崩溃,这时候我们可以进行回滚操作回到数据更新前的状态。

1、日志格式

undo log 格式都有一个 roll_pointer 指针和一个 trx_id 事务id:

  • 通过 trx_id 可以知道该记录是被哪个事务修改的;
  • 通过 roll_pointer 指针可以将这些 undo log串成一个链表,这个链表就被称为版本链;

2、作用

undo log 两大作用:
1)实现事务回滚,保障事务的原子性。事务处理过程中,如果出现了错误或者用户执 行了 ROLLBACK 语句,MySQL 可以利用 undo log 中的历史数据将数据恢复到事务开始之前的状态。
2)实现 MVCC(多版本并发控制)关键因素之一。MVCC 是通过 ReadView + undo log 实现的。undo log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 select 语句)的时候,会根据事务的 Read View 里的信息,顺着 undo log 的版本链找到满足其可见性的记录。

三、BinLog日志

MySQL 在完成一条更新操作后,Server 层还会生成一条 binlog,等之后事务提交的时候,会将该事物执行过程中产生的所有 binlog 统一写 入 binlog 文件。
binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。

1、主从复制

主从复制的工作原理就是slave从库会从master主库读取binlog来进行数据同步。
在这里插入图片描述
上图说明,MySQL主从复制过程分成四步:

从库生成两个线程,一个 I/O 线程,一个 SQL 线程
当从库连接主库时,主库会生成一个 二进制转储(binlog dump) 线程,用来给从库 I/O 线程传 binlog
I/O 线程去请求主库的 binlog,并将得到的 binlog 日志写到 relay log(中继日志) 文件中。(在读取 binlog 的内容的操作中,会对主库的 binlog 加锁,当binlog读取完成并发送给从库后解锁。)
从SQL 线程会读取 relay log 文件中的日志,并解析成具体操作,来实现主从的操作一致,最终实现主从的数据一致。
复制过程有一个很重要的限制,就是复制在从库上是串行化的,也就是说主库上的并行更新操作不能在 从库上并行操作。

2、binlog三种格式

1.Statement:每一条会修改数据的sql都会记录在binlog中。

优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。(相比row能节约多少性能与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该跟据应用的实际情况,其所产生的日志量会增加多少,以及带来的IO性能问题。)

缺点:由于记录的只是执行语句,为了这些语句能在slave上正确运行,因此还必须记录每条语句在执行的时候的一些相关信息,以保证所有语句能在slave得到和在master端执行时候相同的结果。另外mysql 的复制,像一些特定函数功能,slave可与master上要保持一致会有很多相关问题(如sleep()函数, last_insert_id(),以及user-defined functions(udf)会出现问题).

2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。

优点: binlog中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。所以rowlevel的日志内容会非常清楚的记录下每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题

缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。

3.Mixedlevel: 是以上两种level的混合使用,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种.新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,还是会记录所有行的变更。

四、两阶段提交

在这里插入图片描述

1、写redo log的原因

先说结论:在于崩溃恢复。
MySQL为了提升性能,引入了BufferPool缓冲池。查询数据时,先BufferPool中查询,查询不到则从磁盘加载在BufferPool。
每次对数据的更新,也不总是实时刷新到磁盘,而是先同步到BufferPool中,涉及到的数据页就会变成脏页。同时会启动后台线程,异步地将脏页刷新到磁盘中,来完成BufferPool与磁盘的数据同步。如果在某个时间,MySQL突然崩溃,则内存中的BufferPool就会丢失,剩余未同步的数据就会直接消失。
虽然在更新BufferPool后,也写入了binlog中,但binlog并不具备crash-safe的能力。因为崩溃可能发生在写binlog后,刷脏前。在主从同步的情况下,从节点会拿到多出来的一条binlog。所以server层的binlog是不支持崩溃恢复的,只是支持误删数据恢复。InnoDB考虑到这一点,自己实现了redo log。

2、为什么要写两次redo log?

redo log与binlog都写一次的话,也就是存在以下两种情况:
1)先写binlog,再写redo log:当前事务提交后,写入binlog成功,之后主节点崩溃。在主节点重启后,由于没有写入redo log,因此不会恢复该条数据。而从节点依据binlog在本地回放后,会相对于主节点多出来一条数据,从而产生主从不一致。
2)先写redo log,再写binlog:当前事务提交后,写入redo log成功,之后主节点崩溃。在主节点重启后,主节点利用redo log进行恢复,就会相对于从节点多出来一条数据,造成主从数据不一致。
因此,只写一次redo log与binlog,无法保证主节点崩溃恢复与从节点本地回放数据的一致性。

3、在两阶段提交的情况下,是怎么实现崩溃恢复的呢?

首先比较重要的一点是,在写入redo log时,会顺便记录XID,即当前事务id。在写入binlog时,也会写入XID。因此存在以下三种情况:
1)如果在写入redo log之前崩溃,那么此时redo log与binlog中都没有,是一致的情况,崩溃也无所谓。
2)如果在写入redo log prepare阶段后立马崩溃,之后会在崩恢复时,由于redo log没有被标记为commit。于是拿着redo log中的XID去bin log中查找,此时肯定是找不到的,那么执行回滚操作。
3)如果在写入bin log后立马崩溃,在恢复时,由redo log中的XID可以找到对应的bin log,这个时候直接提交即可。
总的来说,在崩溃恢复后,只要redo log不是处于commit阶段,那么就拿着redo log中的XID去binlog中寻找,找得到就提交,否则就回滚。在这样的机制下,两阶段提交能在崩溃恢复时,能够对提交中断的事务进行补偿,来确保redo log与binlog的数据一致性。

五、总结

1、Myisam引擎只支持binlog,而innodb支持binlog、redolog、undolog。
2、Redo Log称为重做日志,用于崩溃后修复数据。在执行修改操作时,sql会先写入到redo.log日志再写入缓存,最后更新数据库,这样即使断电,也能保证数据库不丢失数据,保证了事务的持久性
3、Undo Log称为回滚日志,是Innodb存储引擎生成的日志。用于事务的回滚和MVCC,保证了事务的原子性
4、binlog:是Server层生成的日志。用于备份数据,集群,主从复制等。
5、undolog、redolog是Innodb存储引擎生成的日志;binlog是Server层生成的日志。
6、隔离性:写-写操作通过锁来实现,写-读操作MVCC
7、一致性:从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性;从应用层面,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值