精华内容
下载资源
问答
  • 作为开发,我们重点需要关注的是二进制日志(binlog)和事务日志(包括redo logundo log),本文接下来会详细介绍这三种日志。 binlog binlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在...

    转自:https://juejin.cn/post/6860252224930070536

    日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。作为开发,我们重点需要关注的是二进制日志(binlog)和事务日志(包括redo logundo log),本文接下来会详细介绍这三种日志。

    binlog

    binlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlogmysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。

    逻辑日志:可以简单理解为记录的就是sql语句

    物理日志:因为mysql数据最终是保存在数据页中的,物理日志记录的就是数据页变更

    binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

    binlog使用场景

    在实际应用中,binlog的主要使用场景有两个,分别是主从复制数据恢复

    1. 主从复制:在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致。
    2. 数据恢复:通过使用mysqlbinlog工具来恢复数据。

    binlog刷盘时机

    对于InnoDB存储引擎而言,只有在事务提交时才会记录biglog,此时记录还在内存中,那么biglog是什么时候刷到磁盘中的呢?mysql通过sync_binlog参数控制biglog的刷盘时机,取值范围是0-N

    • 0:不去强制要求,由系统自行判断何时写入磁盘;
    • 1:每次commit的时候都要将binlog写入磁盘;
    • N:每N个事务,才会将binlog写入磁盘。

    从上面可以看出,sync_binlog最安全的是设置是1,这也是MySQL 5.7.7之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。

    binlog日志格式

    binlog日志有三种格式,分别为STATMENTROWMIXED

    MySQL 5.7.7之前,默认的格式是STATEMENTMySQL 5.7.7之后,默认值是ROW。日志格式通过binlog-format指定。

    • STATMENT 基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的sql语句会记录到binlog。 优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO, 从而提高了性能; 缺点:在某些情况下会导致主从数据不一致,比如执行sysdate()slepp()
    • ROW 基于行的复制(row-based replication, RBR),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了。 优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题; 缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨
    • MIXED 基于STATMENTROW两种模式的混合复制(mixed-based replication, MBR),一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog

    redo log

    为什么需要redo log

    我们都知道,事务的四大特性里面有一个是持久性,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态。那么mysql是如何保证持久性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题,主要体现在两个方面:

    1. 因为Innodb是以为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了!
    2. 一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!

    因此mysql设计了redo log具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。

    redo log基本概念

    redo log包括两部分:一个是内存中的日志缓冲(redo log buffer),另一个是磁盘上的日志文件(redo log file)。mysql每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。这种先写日志,再写磁盘的技术就是MySQL里经常说到的WAL(Write-Ahead Logging) 技术。

    在计算机操作系统中,用户空间(user space)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间(kernel space)缓冲区(OS Buffer)。因此,redo log buffer写入redo log file实际上是先写入OS Buffer,然后再通过系统调用fsync()将其刷到redo log file中,过程如下:

    mysql支持三种将redo log buffer写入redo log file的时机,可以通过innodb_flush_log_at_trx_commit参数配置,各参数值含义如下:

    参数值含义
    0(延迟写)事务提交时不会将redo log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到redo log file中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
    1(实时写,实时刷)事务每次提交都会将redo log buffer中的日志写入os buffer并调用fsync()刷到redo log file中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
    2(实时写,延迟刷)每次提交都仅写入到os buffer,然后是每秒调用fsync()os buffer中的日志写入到redo log file

    redo log记录形式

    前面说过,redo log实际上记录数据页的变更,而这种变更记录是没必要全部保存,因此redo log实现上采用了大小固定,循环写入的方式,当写到结尾时,会回到开头循环写日志。如下图:

    同时我们很容易得知,在innodb中,既有redo log需要刷盘,还有数据页也需要刷盘,redo log存在的意义主要就是降低对数据页刷盘的要求。在上图中,write pos表示redo log当前记录的LSN(逻辑序列号)位置,check point表示数据页更改记录刷盘后对应redo log所处的LSN(逻辑序列号)位置。write poscheck point之间的部分是redo log空着的部分,用于记录新的记录;check pointwrite pos之间是redo log待落盘的数据页更改记录。当write pos追上check point时,会先推动check point向前移动,空出位置再记录新的日志。

    启动innodb的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。因为redo log记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如binlog)要快很多。 重启innodb时,首先会检查磁盘中数据页的LSN,如果数据页的LSN小于日志中的LSN,则会从checkpoint开始恢复。 还有一种情况,在宕机前正处于checkpoint的刷盘过程,且数据页的刷盘进度超过了日志页的刷盘进度,此时会出现数据页中记录的LSN大于日志中的LSN,这时超出日志进度的部分将不会重做,因为这本身就表示已经做过的事情,无需再重做。

    redo log与binlog区别

     redo logbinlog
    文件大小redo log的大小是固定的。binlog可通过配置参数max_binlog_size设置每个binlog文件的大小。
    实现方式redo logInnoDB引擎层实现的,并不是所有引擎都有。binlogServer层实现的,所有引擎都可以使用 binlog日志
    记录方式redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。binlog 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上
    适用场景redo log适用于崩溃恢复(crash-safe)binlog适用于主从复制和数据恢复

    binlogredo log的区别可知:binlog日志只用于归档,只依靠binlog是没有crash-safe能力的。但只有redo log也不行,因为redo logInnoDB特有的,且日志上的记录落盘后会被覆盖掉。因此需要binlogredo log二者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。

    undo log

    数据库事务四大特性中有一个是原子性,具体来说就是 原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况。实际上,原子性底层就是通过undo log实现的。undo log主要记录了数据的逻辑变化,比如一条INSERT语句,对应一条DELETEundo log,对于每个UPDATE语句,对应一条相反的UPDATEundo log,这样在发生错误时,就能回滚到事务之前的数据状态。同时,undo log也是MVCC(多版本并发控制)实现的关键,这部分内容在面试中的老大难-mysql事务和锁,一次性讲清楚!中有介绍,不再赘述。

    展开全文
  • undolog的执行逻辑可以理解为: 当 delete 一条记录时,undolog 记录一条对应的 insert 语句 当 insert 一条记录时,undolog 记录一条对应的 delete 语句 当 update 一条记录时,undolog 记录一条对应的返 update...

     

    一条sql的执行流程见下图:

    连接器:

    负责跟客户都建立连接、获取权限、维持和管理连接。

    • 用户名、密码验证
    • 查询权限信息、分配对应的权限
    • 可以使用 show processlist 查看现有的连接
    • 如果长时间没有动静,会字段断开连接,通过 wati_timeout 控制,默认 8 小时 

    查询缓存

    • 当执行 sql 查询语句的时候,会先去查询缓存中查看结果,之前执行过的  sql 语句及其结果可能以 key-value 的形式存储在缓存中。如果能找到则直接返回,如果找不到则执行后边的阶段。
    • 但是不推荐使用查询缓存----》 a、查询缓存失效比较频繁(只要表更新,缓存就会清空),频繁 IO 。b、缓存对应新更新的数据命中率比较地

    分析器

    • 词法分析:Mysql 需要把输入的字符串进行识别每个部分代表什么意思?    把字符串 T 识别成表名 T ;字符串 ID 识别成 列 ID
    • 语法分析:根据语法规则判断这个 sql 语句是否满足mysql 的语法,如果不符合报错 “You have an error in your SQL synta”。

    优化器

    在具体执行 sql 语句之前,要先经过优化器的处理

    • 当表中有多个索引时,决定用哪个索引
    • 当sql 需要多表关联时,决定表的连接顺序

    不同的执行方式对 sql 语句的执行效率影响很大

    • RBO 基于规则的优化
    • CBO 基于成本的优化

    Redo log (事务日志) —— Innodb 存储引擎的日志文件

    1. 记录的是数据库中每个页的修改,可以用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置,因为修改会覆盖之前的)
    2. 当发生数据修改的时候,innodb引擎会先把记录写入 redo log 中,并更新内存,此时更新就算完成了。同时innodb引擎会在合适的时机将记录写到磁盘中
    3. Redo log 是固定大小的,是循环写的过程
    4. 有了 redolog之后,innodb 可以保证即使数据库发生异常重启,之前的记录也不会丢失,叫做 crash-safe

    undo log (回滚日志) —— Innodb 存储引擎的日志文件

    1. undolog 保证事务的原子性,还用undolog日志实现多版本并发控制简称 MVCC
    2. 在操作数据库之前,先将数据备份到 undolog 文件中。然后进行数据的修改,如果出现错误或用户执行 ROLLBACK 语句,系统可以通过 undolog 中的备份数据恢复到事务开始之前的数据。
    3. undolog的执行逻辑可以理解为:
    • 当 delete 一条记录时,undolog 记录一条对应的 insert 语句
    • 当 insert 一条记录时,undolog 记录一条对应的 delete  语句
    • 当 update 一条记录时,undolog 记录一条对应的返 update 语句

    binlog (归档日志) —— 服务端日志文件

    binlog主要用作主从同步和数据库基于时间点的还原。

    Binlog 是 Server 层的日志文件,主要做mysql功能层面的事情,与 Redolog 的区别

    1. redolog 是innodb独有的,binlog 所有引擎都可以用
    2. redolog 是物理日志,记录数据页上的修改,binlog是逻辑日志,记录的是这个语句的原始逻辑
    3. redolog 是循环写的,空间会用完。binlog 是可以追写的,不会覆盖之前的日志信息

     

     

     

     

     

     

     

    展开全文
  • mysql redolog undolog binlog

    2020-06-12 10:58:36
    innodb事务日志包括redo logundo logredo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作。 undo log不是redo log的逆向过程,其实它们都算是用来恢复的日志:1.redo log通常是物理日志,记录...

    更多参考:MySQL--buffer pool、redo log、undo log、binlog_黄智霖的博客-CSDN博客

    https://segmentfault.com/a/1190000023827696

    彻底搞懂MySQL的redo log,binlog,undo log - 掘金

    前言

    mysql 先写到buffer pool,再写日志,再写磁盘。undolog 存储 修改前的原始记录(逻辑日志,如果insert操作,会添加一条相反的delete的sql),redolog存储新的修改数据(记录物理数据页的修改,指定磁盘上数据物理页的地址,两阶段提交,prepare,commit)https://techlog.cn/article/list/10183403。binlog存储所有增删改的时间(有几种日志格式可选SBR,RBR,MBR)https://techlog.cn/article/list/10183401。

    innodb事务日志包括redo log和undo log。redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作。

    undo log不是redo log的逆向过程,其实它们都算是用来恢复的日志:
    1.redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。
    2.undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。

    1.redo log

    1.1 redo log和二进制日志的区别

    二进制日志相关内容,参考:MariaDB/MySQL的二进制日志

    redo log不是二进制日志。虽然二进制日志中也记录了innodb表的很多操作,也能实现重做的功能,但是它们之间有很大区别。

    1. 二进制日志是在存储引擎的上层产生的,不管是什么存储引擎,对数据库进行了修改都会产生二进制日志。而redo log是innodb层产生的,只记录该存储引擎中表的修改。并且二进制日志先于redo log被记录。具体的见后文group commit小结。
    2. 二进制日志记录操作的方法是逻辑性的语句。即便它是基于行格式的记录方式,其本质也还是逻辑的SQL设置,如该行记录的每列的值是多少。而redo log是在物理格式上的日志,它记录的是数据库中每个页的修改。
    3. 二进制日志只在每次事务提交的时候一次性写入缓存中的日志"文件"(对于非事务表的操作,则是每次执行语句成功后就直接写入)。而redo log在数据准备修改前写入缓存中的redo log中,然后才对缓存中的数据执行修改操作;而且保证在发出事务提交指令时,先向缓存中的redo log写入日志,写入完成后才执行提交动作。
    4. 因为二进制日志只在提交的时候一次性写入,所以二进制日志中的记录方式和提交顺序有关,且一次提交对应一次记录。而redo log中是记录的物理页的修改,redo log文件中同一个事务可能多次记录,最后一个提交的事务记录会覆盖所有未提交的事务记录。例如事务T1,可能在redo log中记录了 T1-1,T1-2,T1-3,T1* 共4个操作,其中 T1* 表示最后提交时的日志记录,所以对应的数据页最终状态是 T1* 对应的操作结果。而且redo log是并发写入的,不同事务之间的不同版本的记录会穿插写入到redo log文件中,例如可能redo log的记录方式如下: T1-1,T1-2,T2-1,T2-2,T2*,T1-3,T1* 。
    5. 事务日志记录的是物理页的情况,它具有幂等性,因此记录日志的方式极其简练。幂等性的意思是多次操作前后状态是一样的,例如新插入一行后又删除该行,前后状态没有变化。而二进制日志记录的是所有影响数据的操作,记录的内容较多。例如插入一行记录一次,删除该行又记录一次。

    1.2 redo log的基本概念

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

    在概念上,innodb通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。

    为了确保每次日志都能写入到事务日志文件中,在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(即fsync()系统调用)。因为MariaDB/MySQL是工作在用户空间的,MariaDB/MySQL的log buffer处于用户空间的内存中。要写入到磁盘上的log file中(redo:ib_logfileN文件,undo:share tablespace或.ibd文件),中间还要经过操作系统内核空间的os buffer,调用fsync()的作用就是将OS buffer中的日志刷到磁盘上的log file中。

    也就是说,从redo log buffer写日志到磁盘的redo log file中,过程如下: 

    在此处需要注意一点,一般所说的log file并不是磁盘上的物理日志文件,而是操作系统缓存中的log file,官方手册上的意思也是如此(例如:With a value of 2, the contents of the InnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second)。但说实话,这不太好理解,既然都称为file了,应该已经属于物理文件了。所以在本文后续内容中都以os buffer或者file system buffer来表示官方手册中所说的Log file,然后log file则表示磁盘上的物理日志文件,即log file on disk。

    另外,之所以要经过一层os buffer,是因为open日志文件的时候,open没有使用O_DIRECT标志位,该标志位意味着绕过操作系统层的os buffer,IO直写到底层存储设备。不使用该标志位意味着将日志进行缓冲,缓冲到了一定容量,或者显式fsync()才会将缓冲中的刷到存储设备。使用该标志位意味着每次都要发起系统调用。比如写abcde,不使用o_direct将只发起一次系统调用,使用o_object将发起5次系统调用。

    MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。该变量有3种值:0、1、2,默认为1。但注意,这个变量只是控制commit动作是否刷新log buffer到磁盘。

    • 当设置为1的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
    • 当设置为0的时候,事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
    • 当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。

    注意,有一个变量 innodb_flush_log_at_timeout 的值为1秒,该变量表示的是刷日志的频率,很多人误以为是控制 innodb_flush_log_at_trx_commit 值为0和2时的1秒频率,实际上并非如此。测试时将频率设置为5和设置为1,当 innodb_flush_log_at_trx_commit 设置为0和2的时候性能基本都是不变的。关于这个频率是控制什么的,在后面的"刷日志到磁盘的规则"中会说。

    在主从复制结构中,要保证事务的持久性和一致性,需要对日志相关变量设置为如下:

    • 如果启用了二进制日志,则设置sync_binlog=1,即每提交一次事务同步写到磁盘中。
    • 总是设置innodb_flush_log_at_trx_commit=1,即每提交一次事务都写到磁盘中。

    上述两项变量的设置保证了:每次提交事务都写入二进制日志和事务日志,并在提交时将它们刷新到磁盘中。

    选择刷日志的时间会严重影响数据修改时的性能,特别是刷到磁盘的过程。下例就测试了 innodb_flush_log_at_trx_commit 分别为0、1、2时的差距。

    #创建测试表
    drop table if exists test_flush_log;
    create table test_flush_log(id int,name char(50))engine=innodb;
    
    #创建插入指定行数的记录到测试表中的存储过程
    drop procedure if exists proc;
    delimiter $$
    create procedure proc(i int)
    begin
        declare s int default 1;
        declare c char(50) default repeat('a',50);
        while s<=i do
            start transaction;
            insert into test_flush_log values(null,c);
            commit;
            set s=s+1;
        end while;
    end$$
    delimiter ;

    当前环境下, innodb_flush_log_at_trx_commit 的值为1,即每次提交都刷日志到磁盘。测试此时插入10W条记录的时间。

    mysql> call proc(100000);
    Query OK, 0 rows affected (15.48 sec)

    结果是15.48秒。

    再测试值为2的时候,即每次提交都刷新到os buffer,但每秒才刷入磁盘中。

    mysql> set @@global.innodb_flush_log_at_trx_commit=2;    
    mysql> truncate test_flush_log;
    
    mysql> call proc(100000);
    Query OK, 0 rows affected (3.41 sec)

    结果插入时间大减,只需3.41秒。

    最后测试值为0的时候,即每秒才刷到os buffer和磁盘。

    mysql> set @@global.innodb_flush_log_at_trx_commit=0;
    mysql> truncate test_flush_log;
    
    mysql> call proc(100000);
    Query OK, 0 rows affected (2.10 sec)

    结果只有2.10秒。

    最后可以发现,其实值为2和0的时候,它们的差距并不太大,但2却比0要安全的多。它们都是每秒从os buffer刷到磁盘,它们之间的时间差体现在log buffer刷到os buffer上。因为将log buffer中的日志刷新到os buffer只是内存数据的转移,并没有太大的开销,所以每次提交和每秒刷入差距并不大。可以测试插入更多的数据来比较,以下是插入100W行数据的情况。从结果可见,值为2和0的时候差距并不大,但值为1的性能却差太多。

    尽管设置为0和2可以大幅度提升插入性能,但是在故障的时候可能会丢失1秒钟数据,这1秒钟很可能有大量的数据,从上面的测试结果看,100W条记录也只消耗了20多秒,1秒钟大约有4W-5W条数据,尽管上述插入的数据简单,但却说明了数据丢失的大量性。更好的插入数据的做法是将值设置为1,然后修改存储过程,将每次循环都提交修改为只提交一次这样既能保证数据的一致性,也能提升性能,修改如下:

    drop procedure if exists proc;
    delimiter $$
    create procedure proc(i int)
    begin
        declare s int default 1;
        declare c char(50) default repeat('a',50);
        start transaction;
        while s<=i DO
            insert into test_flush_log values(null,c);
            set s=s+1;
        end while;
        commit;
    end$$
    delimiter ;

    测试值为1时的情况。

    mysql> set @@global.innodb_flush_log_at_trx_commit=1;
    mysql> truncate test_flush_log;
    
    mysql> call proc(1000000);
    Query OK, 0 rows affected (11.26 sec)

    1.3 日志块(log block)

    innodb存储引擎中,redo log以块为单位进行存储的,每个块占512字节,这称为redo log block。所以不管是log buffer中还是os buffer中以及redo log file on disk中,都是这样以512字节的块存储的。

    每个redo log block由3部分组成:日志块头、日志块尾和日志主体。其中日志块头占用12字节,日志块尾占用8字节,所以每个redo log block的日志主体部分只有512-12-8=492字节。

    因为redo log记录的是数据页的变化,当一个数据页产生的变化需要使用超过492字节()的redo log来记录,那么就会使用多个redo log block来记录该数据页的变化。

    日志块头包含4部分:

    • log_block_hdr_no:(4字节)该日志块在redo log buffer中的位置ID。
    • log_block_hdr_data_len:(2字节)该log block中已记录的log大小。写满该log block时为0x200,表示512字节。
    • log_block_first_rec_group:(2字节)该log block中第一个log的开始偏移位置。
    • lock_block_checkpoint_no:(4字节)写入检查点信息的位置。

    关于log block块头的第三部分 log_block_first_rec_group ,因为有时候一个数据页产生的日志量超出了一个日志块,这是需要用多个日志块来记录该页的相关日志。例如,某一数据页产生了552字节的日志量,那么需要占用两个日志块,第一个日志块占用492字节,第二个日志块需要占用60个字节,那么对于第二个日志块来说,它的第一个log的开始位置就是73字节(60+12)。如果该部分的值和 log_block_hdr_data_len 相等,则说明该log block中没有新开始的日志块,即表示该日志块用来延续前一个日志块。

    日志尾只有一个部分: log_block_trl_no ,该值和块头的 log_block_hdr_no 相等。

    上面所说的是一个日志块的内容,在redo log buffer或者redo log file on disk中,由很多log block组成。如下图:

    1.4 log group和redo log file

    log group表示的是redo log group,一个组内由多个大小完全相同的redo log file组成。组内redo log file的数量由变量 innodb_log_files_group 决定,默认值为2,即两个redo log file。这个组是一个逻辑的概念,并没有真正的文件来表示这是一个组,但是可以通过变量 innodb_log_group_home_dir 来定义组的目录,redo log file都放在这个目录下,默认是在datadir下。

    mysql> show global variables like "innodb_log%";
    +-----------------------------+----------+
    | Variable_name               | Value    |
    +-----------------------------+----------+
    | innodb_log_buffer_size      | 8388608  |
    | innodb_log_compressed_pages | ON       |
    | innodb_log_file_size        | 50331648 |
    | innodb_log_files_in_group   | 2        |
    | innodb_log_group_home_dir   | ./       |
    +-----------------------------+----------+
    
    [root@xuexi data]# ll /mydata/data/ib*
    -rw-rw---- 1 mysql mysql 79691776 Mar 30 23:12 /mydata/data/ibdata1
    -rw-rw---- 1 mysql mysql 50331648 Mar 30 23:12 /mydata/data/ib_logfile0
    -rw-rw---- 1 mysql mysql 50331648 Mar 30 23:12 /mydata/data/ib_logfile1

    可以看到在默认的数据目录下,有两个ib_logfile开头的文件,它们就是log group中的redo log file,而且它们的大小完全一致且等于变量 innodb_log_file_size 定义的值。第一个文件ibdata1是在没有开启 innodb_file_per_table 时的共享表空间文件,对应于开启 innodb_file_per_table 时的.ibd文件。

    在innodb将log buffer中的redo log block刷到这些log file中时,会以追加写入的方式循环轮训写入。即先在第一个log file(即ib_logfile0)的尾部追加写,直到满了之后向第二个log file(即ib_logfile1)写。当第二个log file满了会清空一部分第一个log file继续写入。

    由于是将log buffer中的日志刷到log file,所以在log file中记录日志的方式也是log block的方式。

    在每个组的第一个redo log file中,前2KB记录4个特定的部分,从2KB之后才开始记录log block。除了第一个redo log file中会记录,log group中的其他log file不会记录这2KB,但是却会腾出这2KB的空间。如下:

    redo log file的大小对innodb的性能影响非常大,设置的太大,恢复的时候就会时间较长,设置的太小,就会导致在写redo log的时候循环切换redo log file。

    1.5 redo log的格式

    因为innodb存储引擎存储数据的单元是页(和SQL Server中一样),所以redo log也是基于页的格式来记录的。默认情况下,innodb的页大小是16KB(由 innodb_page_size 变量控制),一个页内可以存放非常多的log block(每个512字节),而log block中记录的又是数据页的变化。

    其中log block中492字节的部分是log body,该log body的格式分为4部分:

    • redo_log_type:占用1个字节,表示redo log的日志类型。
    • space:表示表空间的ID,采用压缩的方式后,占用的空间可能小于4字节。
    • page_no:表示页的偏移量,同样是压缩过的。
    • redo_log_body表示每个重做日志的数据部分,恢复时会调用相应的函数进行解析。例如insert语句和delete语句写入redo log的内容是不一样的。

    如下图,分别是insert和delete大致的记录方式。

    1.6 日志刷盘的规则

    log buffer中未刷到磁盘的日志称为脏日志(dirty log)。

    在上面的说过,默认情况下事务每次提交的时候都会刷事务日志到磁盘中,这是因为变量 innodb_flush_log_at_trx_commit 的值为1。但是innodb不仅仅只会在有commit动作后才会刷日志到磁盘,这只是innodb存储引擎刷日志的规则之一。

    刷日志到磁盘有以下几种规则:

    1.发出commit动作时。已经说明过,commit发出后是否刷日志由变量 innodb_flush_log_at_trx_commit 控制。

    2.每秒刷一次。这个刷日志的频率由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。要注意,这个刷日志频率和commit动作无关。

    3.当log buffer中已经使用的内存超过一半时。

    4.当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置。

    1.7 数据页刷盘的规则及checkpoint

    内存中(buffer pool)未刷到磁盘的数据称为脏数据(dirty data)。由于数据和日志都以页的形式存在,所以脏页表示脏数据和脏日志。

    上一节介绍了日志是何时刷到磁盘的,不仅仅是日志需要刷盘,脏数据页也一样需要刷盘。

    在innodb中,数据刷盘的规则只有一个:checkpoint。但是触发checkpoint的情况却有几种。不管怎样,checkpoint触发后,会将buffer中脏数据页和脏日志页都刷到磁盘。

    innodb存储引擎中checkpoint分为两种:

    • sharp checkpoint:在重用redo log文件(例如切换日志文件)的时候,将所有已记录到redo log中对应的脏数据刷到磁盘。
    • fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:
      • master thread checkpoint:由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。
      • flush_lru_list checkpoint:从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。
      • async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
      • dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。

    由于刷脏页需要一定的时间来完成,所以记录检查点的位置是在每次刷盘结束之后才在redo log中标记的。

    MySQL停止时是否将脏数据和脏日志刷入磁盘,由变量innodb_fast_shutdown={ 0|1|2 }控制,默认值为1,即停止时只做一部分purge,忽略大多数flush操作(但至少会刷日志),在下次启动的时候再flush剩余的内容,实现fast shutdown。

    1.8 LSN超详细分析

    LSN称为日志的逻辑序列号(log sequence number),在innodb存储引擎中,lsn占用8个字节。LSN的值会随着日志的写入而逐渐增大。

    根据LSN,可以获取到几个有用的信息:

    1.数据页的版本信息。

    2.写入的日志总量,通过LSN开始号码和结束号码可以计算出写入的日志量。

    3.可知道检查点的位置。

    实际上还可以获得很多隐式的信息。

    LSN不仅存在于redo log中,还存在于数据页中,在每个数据页的头部,有一个fil_page_lsn记录了当前页最终的LSN值是多少。通过数据页中的LSN值和redo log中的LSN值比较,如果页中的LSN值小于redo log中LSN值,则表示数据丢失了一部分,这时候可以通过redo log的记录来恢复到redo log中记录的LSN值时的状态。

    redo log的lsn信息可以通过 show engine innodb status 来查看。MySQL 5.5版本的show结果中只有3条记录,没有pages flushed up to。

    mysql> show engine innodb stauts
    ---
    LOG
    ---
    Log sequence number 2225502463
    Log flushed up to   2225502463
    Pages flushed up to 2225502463
    Last checkpoint at  2225502463
    0 pending log writes, 0 pending chkp writes
    3201299 log i/o's done, 0.00 log i/o's/second

    其中:

    • log sequence number就是当前的redo log(in buffer)中的lsn;
    • log flushed up to是刷到redo log file on disk中的lsn;
    • pages flushed up to是已经刷到磁盘数据页上的LSN;
    • last checkpoint at是上一次检查点所在位置的LSN。

    innodb从执行修改语句开始:

    (1).首先修改内存中的数据页,并在数据页中记录LSN,暂且称之为data_in_buffer_lsn;

    (2).并且在修改数据页的同时(几乎是同时)向redo log in buffer中写入redo log,并记录下对应的LSN,暂且称之为redo_log_in_buffer_lsn;

    (3).写完buffer中的日志后,当触发了日志刷盘的几种规则时,会向redo log file on disk刷入重做日志,并在该文件中记下对应的LSN,暂且称之为redo_log_on_disk_lsn;

    (4).数据页不可能永远只停留在内存中,在某些情况下,会触发checkpoint来将内存中的脏页(数据脏页和日志脏页)刷到磁盘,所以会在本次checkpoint脏页刷盘结束时,在redo log中记录checkpoint的LSN位置,暂且称之为checkpoint_lsn。

    (5).要记录checkpoint所在位置很快,只需简单的设置一个标志即可,但是刷数据页并不一定很快,例如这一次checkpoint要刷入的数据页非常多。也就是说要刷入所有的数据页需要一定的时间来完成,中途刷入的每个数据页都会记下当前页所在的LSN,暂且称之为data_page_on_disk_lsn。

    详细说明如下图:

    上图中,从上到下的横线分别代表:时间轴、buffer中数据页中记录的LSN(data_in_buffer_lsn)、磁盘中数据页中记录的LSN(data_page_on_disk_lsn)、buffer中重做日志记录的LSN(redo_log_in_buffer_lsn)、磁盘中重做日志文件中记录的LSN(redo_log_on_disk_lsn)以及检查点记录的LSN(checkpoint_lsn)。

    假设在最初时(12:0:00)所有的日志页和数据页都完成了刷盘,也记录好了检查点的LSN,这时它们的LSN都是完全一致的。

    假设此时开启了一个事务,并立刻执行了一个update操作,执行完成后,buffer中的数据页和redo log都记录好了更新后的LSN值,假设为110。这时候如果执行 show engine innodb status 查看各LSN的值,即图中①处的位置状态,结果会是:

    log sequence number(110) > log flushed up to(100) = pages flushed up to = last checkpoint at

    之后又执行了一个delete语句,LSN增长到150。等到12:00:01时,触发redo log刷盘的规则(其中有一个规则是 innodb_flush_log_at_timeout 控制的默认日志刷盘频率为1秒),这时redo log file on disk中的LSN会更新到和redo log in buffer的LSN一样,所以都等于150,这时 show engine innodb status ,即图中②的位置,结果将会是:

    log sequence number(150) = log flushed up to > pages flushed up to(100) = last checkpoint at

    再之后,执行了一个update语句,缓存中的LSN将增长到300,即图中③的位置。

    假设随后检查点出现,即图中④的位置,正如前面所说,检查点会触发数据页和日志页刷盘,但需要一定的时间来完成,所以在数据页刷盘还未完成时,检查点的LSN还是上一次检查点的LSN,但此时磁盘上数据页和日志页的LSN已经增长了,即:

    log sequence number > log flushed up to 和 pages flushed up to > last checkpoint at

    但是log flushed up to和pages flushed up to的大小无法确定,因为日志刷盘可能快于数据刷盘,也可能等于,还可能是慢于。但是checkpoint机制有保护数据刷盘速度是慢于日志刷盘的:当数据刷盘速度超过日志刷盘时,将会暂时停止数据刷盘,等待日志刷盘进度超过数据刷盘。

    等到数据页和日志页刷盘完毕,即到了位置⑤的时候,所有的LSN都等于300。

    随着时间的推移到了12:00:02,即图中位置⑥,又触发了日志刷盘的规则,但此时buffer中的日志LSN和磁盘中的日志LSN是一致的,所以不执行日志刷盘,即此时 show engine innodb status 时各种lsn都相等。

    随后执行了一个insert语句,假设buffer中的LSN增长到了800,即图中位置⑦。此时各种LSN的大小和位置①时一样。

    随后执行了提交动作,即位置⑧。默认情况下,提交动作会触发日志刷盘,但不会触发数据刷盘,所以 show engine innodb status 的结果是:

    log sequence number = log flushed up to > pages flushed up to = last checkpoint at

    最后随着时间的推移,检查点再次出现,即图中位置⑨。但是这次检查点不会触发日志刷盘,因为日志的LSN在检查点出现之前已经同步了。假设这次数据刷盘速度极快,快到一瞬间内完成而无法捕捉到状态的变化,这时 show engine innodb status 的结果将是各种LSN相等。

    1.9 innodb的恢复行为

    在启动innodb的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。

    因为redo log记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如二进制日志)要快很多。而且,innodb自身也做了一定程度的优化,让恢复速度变得更快。

    重启innodb时,checkpoint表示已经完整刷到磁盘上data page上的LSN,因此恢复时仅需要恢复从checkpoint开始的日志部分。例如,当数据库在上一次checkpoint的LSN为10000时宕机,且事务是已经提交过的状态。启动数据库时会检查磁盘中数据页的LSN,如果数据页的LSN小于日志中的LSN,则会从检查点开始恢复。

    还有一种情况,在宕机前正处于checkpoint的刷盘过程,且数据页的刷盘进度超过了日志页的刷盘进度。这时候一宕机,数据页中记录的LSN就会大于日志页中的LSN,在重启的恢复过程中会检查到这一情况,这时超出日志进度的部分将不会重做,因为这本身就表示已经做过的事情,无需再重做。

    另外,事务日志具有幂等性,所以多次操作得到同一结果的行为在日志中只记录一次。而二进制日志不具有幂等性,多次操作会全部记录下来,在恢复的时候会多次执行二进制日志中的记录,速度就慢得多。例如,某记录中id初始值为2,通过update将值设置为了3,后来又设置成了2,在事务日志中记录的将是无变化的页,根本无需恢复;而二进制会记录下两次update操作,恢复时也将执行这两次update操作,速度比事务日志恢复更慢。

    1.10 和redo log有关的几个变量

    • innodb_flush_log_at_trx_commit={0|1|2} # 指定何时将事务日志刷到磁盘,默认为1。
      • 0表示每秒将"log buffer"同步到"os buffer"且从"os buffer"刷到磁盘日志文件中。
      • 1表示每事务提交都将"log buffer"同步到"os buffer"且从"os buffer"刷到磁盘日志文件中。
      • 2表示每事务提交都将"log buffer"同步到"os buffer"但每秒才从"os buffer"刷到磁盘日志文件中。
    • innodb_log_buffer_size:# log buffer的大小,默认8M
    • innodb_log_file_size:#事务日志的大小,默认5M
    • innodb_log_files_group =2:# 事务日志组中的事务日志文件个数,默认2个
    • innodb_log_group_home_dir =./:# 事务日志组路径,当前目录表示数据目录
    • innodb_mirrored_log_groups =1:# 指定事务日志组的镜像组个数,但镜像功能好像是强制关闭的,所以只有一个log group。在MySQL5.7中该变量已经移除。

    2.undo log

    2.1 基本概念

    undo log有两个作用:提供回滚和多个行版本控制(MVCC)。

    在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。

    undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

    当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。

    undo log是采用段(segment)的方式来记录的,每个undo操作在记录的时候占用一个undo log segment

    另外,undo log也会产生redo log,因为undo log也要实现持久性保护。

    2.2 undo log的存储方式

    innodb存储引擎对undo的管理采用段的方式。rollback segment称为回滚段,每个回滚段中有1024个undo log segment

    在以前老版本,只支持1个rollback segment,这样就只能记录1024个undo log segment。后来MySQL5.5可以支持128个rollback segment,即支持128*1024个undo操作,还可以通过变量 innodb_undo_logs (5.6版本以前该变量是 innodb_rollback_segments )自定义多少个rollback segment,默认值为128。

    undo log默认存放在共享表空间中。

    [root@xuexi data]# ll /mydata/data/ib*
    -rw-rw---- 1 mysql mysql 79691776 Mar 31 01:42 /mydata/data/ibdata1
    -rw-rw---- 1 mysql mysql 50331648 Mar 31 01:42 /mydata/data/ib_logfile0
    -rw-rw---- 1 mysql mysql 50331648 Mar 31 01:42 /mydata/data/ib_logfile1

    如果开启了 innodb_file_per_table ,将放在每个表的.ibd文件中。

    在MySQL5.6中,undo的存放位置还可以通过变量 innodb_undo_directory 来自定义存放目录,默认值为"."表示datadir。

    默认rollback segment全部写在一个文件中,但可以通过设置变量 innodb_undo_tablespaces 平均分配到多少个文件中。该变量默认值为0,即全部写入一个表空间文件。该变量为静态变量,只能在数据库示例停止状态下修改,如写入配置文件或启动时带上对应参数。但是innodb存储引擎在启动过程中提示,不建议修改为非0的值,如下:

    2017-03-31 13:16:00 7f665bfab720 InnoDB: Expected to open 3 undo tablespaces but was able
    2017-03-31 13:16:00 7f665bfab720 InnoDB: to find only 0 undo tablespaces.
    2017-03-31 13:16:00 7f665bfab720 InnoDB: Set the innodb_undo_tablespaces parameter to the
    2017-03-31 13:16:00 7f665bfab720 InnoDB: correct value and retry. Suggested value is 0

    2.3 和undo log相关的变量

    undo相关的变量在MySQL5.6中已经变得很少。如下:它们的意义在上文中已经解释了。

     mysql> show variables like "%undo%";
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | innodb_undo_directory   | .     |
    | innodb_undo_logs        | 128   |
    | innodb_undo_tablespaces | 0     |
    +-------------------------+-------+

    2.4 delete/update操作的内部机制

    当事务提交的时候,innodb不会立即删除undo log,因为后续还可能会用到undo log,如隔离级别为repeatable read时,事务读取的都是开启事务时的最新提交行版本,只要该事务不结束,该行版本就不能删除,即undo log不能删除。

    但是在事务提交的时候,会将该事务对应的undo log放入到删除列表中,未来通过purge来删除。并且提交事务时,还会判断undo log分配的页是否可以重用,如果可以重用,则会分配给后面来的事务,避免为每个独立的事务分配独立的undo log页而浪费存储空间和性能。

    通过undo log记录delete和update操作的结果发现:(insert操作无需分析,就是插入行而已)

    • delete操作实际上不会直接删除,而是将delete对象打上delete flag,标记为删除,最终的删除操作是purge线程完成的。
    • update分为两种情况:update的列是否是主键列。
      • 如果不是主键列,在undo log中直接反向记录是如何update的。即update是直接进行的。
      • 如果是主键列,update分两部执行:先删除该行,再插入一行目标行。

     

    3.binlog和事务日志的先后顺序及group commit

    如果事务不是只读事务,即涉及到了数据的修改,默认情况下会在commit的时候调用fsync()将日志刷到磁盘,保证事务的持久性。

    但是一次刷一个事务的日志性能较低,特别是事务集中在某一时刻时事务量非常大的时候。innodb提供了group commit功能,可以将多个事务的事务日志通过一次fsync()刷到磁盘中。

    redolog 和binlog 日志顺序

    在MySQL5.6以前,当事务提交(即发出commit指令)后,MySQL接收到该信号进入 prepare commit 阶段;进入prepare阶段后,立即写内存中的二进制日志,写完内存中的二进制日志后就相当于确定了commit操作;然后开始写内存中的事务日志;最后将二进制日志和事务日志刷盘,它们如何刷盘,分别由变量 sync_binlog 和 innodb_flush_log_at_trx_commit 控制。

    但因为要保证二进制日志和事务日志的一致性,在提交后的prepare阶段会启用一个prepare_commit_mutex锁来保证它们的顺序性和一致性。但这样会导致开启二进制日志后group commmit失效,特别是在主从复制结构中,几乎都会开启二进制日志。

    在MySQL5.6中进行了改进。提交事务时,在存储引擎层的上一层结构中会将事务按序放入一个队列,队列中的第一个事务称为leader,其他事务称为follower,leader控制着follower的行为。虽然顺序还是一样先刷二进制,再刷事务日志,但是机制完全改变了:删除了原来的prepare_commit_mutex行为,也能保证即使开启了二进制日志,group commit也是有效的。

    MySQL5.6中分为3个步骤:flush阶段、sync阶段、commit阶段。

    • flush阶段:向内存中写入每个事务的二进制日志。
    • sync阶段:将内存中的二进制日志刷盘。若队列中有多个事务,那么仅一次fsync操作就完成了二进制日志的刷盘操作。这在MySQL5.6中称为BLGC(binary log group commit)。
    • commit阶段:leader根据顺序调用存储引擎层事务的提交,由于innodb本就支持group commit,所以解决了因为锁 prepare_commit_mutex 而导致的group commit失效问题。

    在flush阶段写入二进制日志到内存中,但是不是写完就进入sync阶段的,而是要等待一定的时间,多积累几个事务的binlog一起进入sync阶段,等待时间由变量 binlog_max_flush_queue_time 决定,默认值为0表示不等待直接进入sync,设置该变量为一个大于0的值的好处是group中的事务多了,性能会好一些,但是这样会导致事务的响应时间变慢,所以建议不要修改该变量的值,除非事务量非常多并且不断的在写入和更新。

    进入到sync阶段,会将binlog从内存中刷入到磁盘,刷入的数量和单独的二进制日志刷盘一样,由变量 sync_binlog 控制。

    当有一组事务在进行commit阶段时,其他新事务可以进行flush阶段,它们本就不会相互阻塞,所以group commit会不断生效。当然,group commit的性能和队列中的事务数量有关,如果每次队列中只有1个事务,那么group commit和单独的commit没什么区别,当队列中事务越来越多时,即提交事务越多越快时,group commit的效果越明显。

    binlog

    binlog 即二进制日志,他记录了引起或可能引起数据库改变事件,包括事件发生的时间、开始位置、结束位置等信息,select、show 等查询语句不会引起数据库改变,因此不会被记录在 binlog 中

    对于事务的执行,只有事务提交时才会一次性写入 binlog,对于非事务操作,则每次语句执行成功后都会直接写入 binlog

    因此,基于 binlog,我们可以看到每一次对数据库的修改是在何时以何种方式执行的,从而可以实现对任意条操作的回滚,当然

    众所周知,mysql 的主从同步机制也是依赖 binlog 来实现的,binlog 让从数据库可以精准还原主库的每一个操作

    此前的文章中,我们已经介绍了如何搭建一个分布式 mysql 主从集群:

    MySQL 分布式主从读写分离架构及实战

    binlog 相关配置

    mysql 默认是不开启 binlog 的,可以在启动时通过 --log-bin=[on|off|file_name] 参数来指定是否开启 binlog

    如果没有给定file_name,则默认为datadir下的主机名加"-bin",并在后面跟上一串数字表示日志序列号,如果给定的日志文件中包含了后缀(logname.suffix)将忽略后缀部分

    也可以通过在配置文件中配置下列选项来开启 binlog 及相关配置:

    mysql 官方测试表明,开启 binlog 后,因记录 binlog 造成的性能损耗小于 1%,所以为了数据安全,强烈建议开启 binlog

    且二进制目的是为了恢复定点数据库和主从复制,所以出于安全和功能考虑,极不建议将二进制日志和datadir放在同一磁盘上

    binlog 日志格式

    上面的配置项中,有一项是 binlog_format,他指定了 binlog 的日志格式,有以下三个选项可选

    STATEMENT 模式(SBR)

    mysql binlog 的默认格式

    在这个模式下,binlog 只会记录可能引起数据变更的 sql 语句

    优点

    这个模式下,因为没有记录实际的数据,所以日志量和 IO 都消耗很低,性能是最优的

    缺点

    但有些操作并不是确定的,比如 uuid() 函数会随机产生唯一标识,当依赖 binlog 回放时,该操作生成的数据与原数据必然是不同的,此时可能造成无法预料的后果

    由于所有的操作都依赖于先后顺序,所以像使用 AUTO_INCREMENT 生成主键 id 的 insert 方法、数据的恢复等都必须串行执行

    ROW 模式(RBR)

    在该模式下,binlog 会记录每次操作的源数据与修改后的目标数据,而不会记录 sql 语句,从 mysql 5.6.2 版本开始,你可以通过在配置文件中指定 binlog_rows_query_log_events 配置项为 0 或 1 来决定是否同时记录 sql 语句

    但对于 GRANT,REVOKE,SET PASSWORD 等管理语句仍然是以 SBR 方式来进行记录的

    优点

    他的主要优势在于可以绝对精准的还原,从而保证了数据的安全与可靠

    并且复制和数据恢复过程可以是并发进行的

    缺点

    该模式最大的缺点在于 binlog 体积会非常大,同时,对于修改记录多、字段长度大的操作来说,RBR 记录时性能消耗会很严重

    同时,由于数据是通过二进制方式记录,无法直观的看到 binlog 究竟记录了什么信息

    MIXED 模式(MBR)

    顾名思义,MIXED 模式是对上述两种模式的混合使用,对于绝大部分操作,都使用 SBR 来进行 binlog 的记录,只有以下操作使用 RBR 来实现:

    1. 表的存储引擎为 NDB
    2. 使用了uuid()、user()、current_user()、found_rows()、row_count()、sysdate() 等不确定函数(now() 函数仍然会以 SBR 方式记录)
    3. 使用了 insert delay 语句
    4. 使用了临时表

    binlog 的查看

    基本信息的查看 -- show 命令

    通过 show 命令可以查看 mysql 的对应信息

    查看 binlog 基本信息

    show master status

    这个命令实现了当前记录的日志文件、偏移量等信息

    查看有哪些 binlog 日志

    show binary logs

    show master logs

    上述两个命令是完全一样的,他显示了目前存在哪些具体的 binlog 文件

    查看 binlog 中记录的详情信息

    SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos]

    这个命令查询了 binlog 中记录的具体信息

    mysql binlog 管理工具 -- mysqlbinlog

    mysqlbinlog [option] log-file1 log-file2...

    -d,--database=name:只查看指定数据库的日志操作

    -o,--offset=#:展示的起始偏移

    -r,--result-file=name:将输出的日志信息输出到指定的文件中,使用重定向也一样可以。

    -s,--short-form:显示简单格式的日志,只记录一些普通的语句,会省略掉一些额外的信息如位置信息和时间信息以及基于行的日志。可以用来调试,生产环境千万不可使用

    --set-charset=char_name:在输出日志信息到文件中时,在文件第一行加上set names char_name

    --start-datetime,--stop-datetime:指定输出开始时间和结束时间内的所有日志信息

    --start-position=#,--stop-position=#:指定输出开始位置和结束位置内的所有日志信息

    -v,-vv:显示更详细信息,基于row的日志默认不会显示出来,此时使用-v或-vv可以查看

    通过 mysqlbinlog 工具,我们可以详细分析 binlog 中的所有信息

    清理 binlog

    删除全部日志

    reset master

    这个命令会删除所有 binlog,并让日志文件从 000001 开始重新记录和生成

    删除指定日志/时间前的所有日志

    有时由于 binlog 占用磁盘空间过大,我们会希望只保留最近的几个文件或指定日期后的文件

    通过下面的命令就可以实现了:

    purge master logs to 'filename'

    purge master logs before 'yyyy-mm-dd hh:mi:ss'

    清理指定文件之前的所有 binlog 文件

    purge master logs to "mysql-bin.000006"

    清理指定时间前的所有 binlog 文件记录

    purge master logs before '2019-03-29 07:36:40'

    通过 binlog 定点还原数据库

    我们开启 binlog 一个十分重要的目的是为了能够随时还原和回滚到近期某个时间节点

    通常,我们会每隔一段时间全量备份一次数据库,而在两次备份之间,则使用 binlog 提供精准的定点回滚功能

    首先,清空数据库,导入上一次备份,然后执行:

    mysqlbinlog --stop-datetime="2019-07-02 15:27:48" /tmp/mysql-bin.000008 | mysql -u user -p password

    于是,数据库成功回滚到 2019-07-02 15:27:48 时刻

    参考:详细分析MySQL事务日志(redo log和undo log) - 骏马金龙 - 博客园

           史上最详尽,一文讲透 MVCC 实现原理_居士的CSDN-CSDN博客_mvcc实现原理

    https://techlog.cn/article/list/10183403

    https://techlog.cn/article/list/10183401

    展开全文
  • 阅读目录(Content)1 undo1.1 undo是啥1.2 undo参数1.3 undo空间管理2 redo2.1 redo是啥2.2 redo 参数2.3 redo 空间管理3 undoredo如何记录事务3.1 Undo + Redo事务的简化过程3.2  IO影响3.3 恢复   ...


        在数据库系统中,既有存放数据的文件,也有存放日志的文件。日志在内存中也是有缓存Log buffer,也有磁盘文件log file,本文主要描述存放日志的文件。

        MySQL中的日志文件,有这么两类常常讨论到:undo日志与redo日志。

    1 undo

    1.1 undo是啥

    undo日志用于存放数据修改被修改前的值,假设修改 tba 表中 id=2的行数据,把Name='B' 修改为Name = 'B2' ,那么undo日志就会用来存放Name='B'的记录,如果这个修改出现异常,可以使用undo日志来实现回滚操作,保证事务的一致性。
    对数据的变更操作,主要来自 INSERT UPDATE DELETE,而UNDO LOG中分为两种类型,一种是 INSERT_UNDO(INSERT操作),记录插入的唯一键值;一种是 UPDATE_UNDO(包含UPDATE及DELETE操作),记录修改的唯一键值以及old column记录。
    IdName
    1A
    2B
    3C
    4
    D

    1.2 undo参数

    MySQL跟undo有关的参数设置有这些:
    复制代码
     1 mysql> show global variables like '%undo%';
     2 +--------------------------+------------+
     3 | Variable_name            | Value      |
     4 +--------------------------+------------+
     5 | innodb_max_undo_log_size | 1073741824 |
     6 | innodb_undo_directory    | ./         |
     7 | innodb_undo_log_truncate | OFF        |
     8 | innodb_undo_logs         | 128        |
     9 | innodb_undo_tablespaces  | 3          |
    10 +--------------------------+------------+
    11  
    12 mysql> show global variables like '%truncate%';
    13 +--------------------------------------+-------+
    14 | Variable_name                        | Value |
    15 +--------------------------------------+-------+
    16 | innodb_purge_rseg_truncate_frequency | 128   |
    17 | innodb_undo_log_truncate             | OFF   |
    18 +--------------------------------------+-------+
    复制代码
    • innodb_max_undo_log_size
        控制最大undo tablespace文件的大小,当启动了innodb_undo_log_truncate 时,undo tablespace  超过innodb_max_undo_log_size 阀值时才会去尝试truncate。该值默认大小为1G,truncate后的大小默认为10M。
    • innodb_undo_tablespaces 
        设置undo独立表空间个数,范围为0-128, 默认为0,0表示表示不开启独立undo表空间 且 undo日志存储在ibdata文件中。该参数只能在最开始初始化MySQL实例的时候指定,如果实例已创建,这个参数是不能变动的,如果在数据库配置文 件 .cnf 中指定innodb_undo_tablespaces 的个数大于实例创建时的指定个数,则会启动失败,提示该参数设置有误。
        如果设置了该参数为n(n>0),那么就会在undo目录下创建n个undo文件(undo001,undo002 ...... undo n),每个文件默认大小为10M.
    什么时候需要来设置这个参数呢?
        当DB写压力较大时,可以设置独立UNDO表空间,把UNDO LOG从ibdata文件中分离开来,指定 innodb_undo_directory目录存放,可以制定到高速磁盘上,加快UNDO LOG 的读写性能。
    • innodb_undo_log_truncate
       InnoDB的purge线程,根据innodb_undo_log_truncate设置开启或关闭、innodb_max_undo_log_size的参数值,以及truncate的频率来进行空间回收和 undo file 的重新初始化。
       该参数生效的前提是,已设置独立表空间且独立表空间个数大于等于2个。
       purge线程在truncate undo log file的过程中,需要检查该文件上是否还有活动事务,如果没有,需要把该undo log file标记为不可分配,这个时候,undo log 都会记录到其他文件上,所以至少需要2个独立表空间文件,才能进行truncate 操作,标注不可分配后,会创建一个独立的文件undo_<space_id>_trunc.log,记录现在正在truncate 某个undo log文件,然后开始初始化undo log file到10M,操作结束后,删除表示truncate动作的 undo_<space_id>_trunc.log 文件,这个文件保证了即使在truncate过程中发生了故障重启数据库服务,重启后,服务发现这个文件,也会继续完成truncate操作,删除文件结束后,标识该undo log file可分配。
    • innodb_purge_rseg_truncate_frequency
      用于控制purge回滚段的频度,默认为128。假设设置为n,则说明,当Innodb Purge操作的协调线程 purge事务128次时,就会触发一次History purge,检查当前的undo log 表空间状态是否会触发truncate。

    1.3 undo空间管理

    如果需要设置独立表空间,需要在初始化数据库实例的时候,指定独立表空间的数量。
    UNDO内部由多个回滚段组成,即 Rollback segment,一共有128个,保存在ibdata系统表空间中,分别从resg slot0 - resg slot127,每一个resg slot,也就是每一个回滚段,内部由1024个undo segment 组成。
    回滚段(rollback segment)分配如下:
    • slot 0 ,预留给系统表空间;
    • slot 1- 32,预留给临时表空间,每次数据库重启的时候,都会重建临时表空间;
    • slot33-127,如果有独立表空间,则预留给UNDO独立表空间;如果没有,则预留给系统表空间;
    回滚段中除去32个提供给临时表事务使用,剩下的 128-32=96个回滚段,可执行 96*1024 个并发事务操作,每个事务占用一个 undo segment slot,注意,如果事务中有临时表事务,还会在临时表空间中的 undo segment slot 再占用一个 undo segment slot,即占用2个undo segment slot。如果错误日志中有: Cannot find a free slot for an undo log。则说明并发的事务太多了,需要考虑下是否要分流业务。
    回滚段(rollback segment )采用 轮询调度的方式来分配使用,如果设置了独立表空间,那么就不会使用系统表空间回滚段中undo segment,而是使用独立表空间的,同时,如果回顾段正在 Truncate操作,则不分配。

    2 redo

    2.1 redo是啥

        当数据库对数据做修改的时候,需要把数据页从磁盘读到buffer pool中,然后在buffer pool中进行修改,那么这个时候buffer pool中的数据页就与磁盘上的数据页内容不一致,称buffer pool的数据页为dirty page 脏数据,如果这个时候发生非正常的DB服务重启,那么这些数据还没在内存,并没有同步到磁盘文件中(注意,同步到磁盘文件是个随机IO),也就是会发生数据丢失,如果这个时候,能够在有一个文件,当buffer pool 中的data page变更结束后,把相应修改记录记录到这个文件(注意,记录日志是顺序IO),那么当DB服务发生crash的情况,恢复DB的时候,也可以根据这个文件的记录内容,重新应用到磁盘文件,数据保持一致。
        这个文件就是redo log ,用于记录 数据修改后的记录,顺序记录。它可以带来这些好处:
    • 当buffer pool中的dirty page 还没有刷新到磁盘的时候,发生crash,启动服务后,可通过redo log 找到需要重新刷新到磁盘文件的记录;
    • buffer pool中的数据直接flush到disk file,是一个随机IO,效率较差,而把buffer pool中的数据记录到redo log,是一个顺序IO,可以提高事务提交的速度;
        假设修改 tba 表中 id=2的行数据,把Name='B' 修改为Name = 'B2' ,那么redo日志就会用来存放Name='B2'的记录,如果这个修改在flush 到磁盘文件时出现异常,可以使用redo log实现重做操作,保证事务的持久性。
    IdName
    1A
    2B
    3C
    4
    D
     
        这里注意下redo log 跟binary log 的区别,redo log 是存储引擎层产生的,而binary log是数据库层产生的。假设一个大事务,对tba做10万行的记录插入,在这个过程中,一直不断的往redo log顺序记录,而binary log不会记录,知道这个事务提交,才会一次写入到binary log文件中。binary log的记录格式有3种:row,statement跟mixed,不同格式记录形式不一样。

    2.2 redo 参数

    • innodb_log_files_in_group
    redo log 文件的个数,命名方式如:ib_logfile0,iblogfile1... iblogfilen。默认2个,最大100个。
    • innodb_log_file_size
    文件设置大小,默认值为 48M,最大值为512G,注意最大值指的是整个 redo log系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大于最大值512G。
    • innodb_log_group_home_dir
    文件存放路径
    • innodb_log_buffer_size
    Redo Log 缓存区,默认8M,可设置1-8M。延迟事务日志写入磁盘,把redo log 放到该缓冲区,然后根据 innodb_flush_log_at_trx_commit参数的设置,再把日志从buffer 中flush 到磁盘中。
    • innodb_flush_log_at_trx_commit
    • innodb_flush_log_at_trx_commit=1,每次commit都会把redo log从redo log buffer写入到system,并fsync刷新到磁盘文件中。
    • innodb_flush_log_at_trx_commit=2,每次事务提交时MySQL会把日志从redo log buffer写入到system,但只写入到file system buffer,由系统内部来fsync到磁盘文件。如果数据库实例crash,不会丢失redo log,但是如果服务器crash,由于file system buffer还来不及fsync到磁盘文件,所以会丢失这一部分的数据。
    • innodb_flush_log_at_trx_commit=0,事务发生过程,日志一直激励在redo log buffer中,跟其他设置一样,但是在事务提交时,不产生redo 写操作,而是MySQL内部每秒操作一次,从redo log buffer,把数据写入到系统中去。如果发生crash,即丢失1s内的事务修改操作。
    • 注意:由于进程调度策略问题,这个“每秒执行一次 flush(刷到磁盘)操作”并不是保证100%的“每秒”。
     

    2.3 redo 空间管理

        Redo log文件以 ib_logfile[number]命名,Redo log 以顺序的方式写入文件文件,写满时则回溯到第一个文件,进行覆盖写。(但在做redo checkpoint时,也会更新第一个日志文件的头部checkpoint标记,所以严格来讲也不算顺序写)。
    实际上redo log有两部分组成:redo log buffer 跟redo log file。buffer pool中把数据修改情况记录到redo log buffer,出现以下情况,再把redo log刷下到redo log file:
    • Redo log buffer空间不足
    • 事务提交(依赖innodb_flush_log_at_trx_commit参数设置)
    • 后台线程
    • 做checkpoint
    • 实例shutdown
    • binlog切换

    3 undo及redo如何记录事务

    这部分内容推荐阅读这系列的博客,写的好好 http://www.zhdba.com/mysqlops/2012/04/06/innodb-log1/
    以下内容部分节选自这博客,感谢作者总结,深入浅出超好理解。

    3.1 Undo + Redo事务的简化过程

      假设有A、B两个数据,值分别为1,2,开始一个事务,事务的操作内容为:把1修改为3,2修改为4,那么实际的记录如下(简化):
      A.事务开始.
      B.记录A=1到undo log.
      C.修改A=3.
      D.记录A=3到redo log.
      E.记录B=2到undo log.
      F.修改B=4.
      G.记录B=4到redo log.
      H.将redo log写入磁盘。
      I.事务提交

    3.2  IO影响

      Undo + Redo的设计主要考虑的是提升IO性能,增大数据库吞吐量。可以看出,B D E G H,均是新增操作,但是B D E G 是缓冲到buffer区,只有G是增加了IO操作,为了保证Redo Log能够有比较好的IO性能,InnoDB 的 Redo Log的设计有以下几个特点:
     
      A. 尽量保持Redo Log存储在一段连续的空间上。因此在系统第一次启动时就会将日志文件的空间完全分配。 以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。
      B. 批量写入日志。日志并不是直接写入文件,而是先写入redo log buffer.当需要将日志刷新到磁盘时 (如事务提交),将许多日志一起写入磁盘.
      C. 并发的事务共享Redo Log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起,
         以减少日志占用的空间。例如,Redo Log中的记录内容可能是这样的:
         记录1: <trx1, insert …>
         记录2: <trx2, update …>
         记录3: <trx1, delete …>
         记录4: <trx3, update …>
         记录5: <trx2, insert …>
      D. 因为C的原因,当一个事务将Redo Log写入磁盘时,也会将其他未提交的事务的日志写入磁盘。
      E. Redo Log上只进行顺序追加的操作,当一个事务需要回滚时,它的Redo Log记录也不会从Redo Log中删除掉。

    3.3 恢复

    前面说到未提交的事务和回滚了的事务也会记录Redo Log,因此在进行恢复时,这些事务要进行特殊的的处理。有2种不同的恢复策略:
     
      A. 进行恢复时,只重做已经提交了的事务。
      B. 进行恢复时,重做所有事务包括未提交的事务和回滚了的事务。然后通过Undo Log回滚那些
         未提交的事务。
     
      MySQL数据库InnoDB存储引擎使用了B策略, InnoDB存储引擎中的恢复机制有几个特点:
     
      A. 在重做Redo Log时,并 不关心事务性。 恢复时,没有BEGIN,也没有COMMIT,ROLLBACK的行为。也不关心每个日志是哪个事务的。尽管事务ID等事务相关的内容会记入Redo Log,这些内容只是被当作要操作的数据的一部分。
      B. 使用B策略就必须要将Undo Log持久化,而且必须要在写Redo Log之前将对应的Undo Log写入磁盘。Undo和Redo Log的这种关联,使得持久化变得复杂起来。为了降低复杂度,InnoDB将Undo Log看作数据,因此记录Undo Log的操作也会记录到redo log中。这样undo log就可以象数据一样缓存起来,而不用在redo log之前写入磁盘了。
         包含Undo Log操作的Redo Log,看起来是这样的:
         记录1: <trx1, Undo log insert <undo_insert …>>
         记录2: <trx1, insert …>
         记录3: <trx2,  Undo log insert <undo_update …>>
         记录4: <trx2, update …>
         记录5: <trx3, Undo log insert <undo_delete …>>
         记录6: <trx3, delete …>
      C. 到这里,还有一个问题没有弄清楚。既然Redo没有事务性,那岂不是会重新执行被回滚了的事务?
         确实是这样。同时Innodb也会将事务回滚时的操作也记录到redo log中。回滚操作本质上也是
         对数据进行修改,因此回滚时对数据的操作也会记录到Redo Log中。
         一个回滚了的事务的Redo Log,看起来是这样的:
         记录1: <trx1, Undo log insert <undo_insert …>>
         记录2: <trx1, insert A…>
         记录3: <trx1, Undo log insert <undo_update …>>
         记录4: <trx1, update B…>
         记录5: <trx1, Undo log insert <undo_delete …>>
         记录6: <trx1, delete C…>
         记录7: <trx1, insert C>
         记录8: <trx1, update B to old value>
         记录9: <trx1, delete A>
         一个被回滚了的事务在恢复时的操作就是先redo再undo,因此不会破坏数据的一致性。
     

    http://mysql.taobao.org/monthly/2015/04/01/

    展开全文
  • 文章目录一、MySQL日志文件类型二、几种日志的对比2-1、用途 redo log undo log binlog2-2、存储内容、格式 redo log undo log binlog2-3、日志生成 redo log undo log binlog2-4、删除策略 redo log ...
  • 而Mysql日志又分为错误日志、查询日志、慢查询日志、二进制日志(binlog)和事务日志(redo logundo log)。其中在我们开发中聊的比较多的就是二进制日志(binlog)和事务日志(redo logundo log)。其实慢查询日志也是...
  • https://zhuanlan.zhihu.com/p/190886874 https://www.jianshu.com/p/f242bc1e95ff https://www.geeksforgeeks.org/shadow-paging-dbms/ https://zhuanlan.zhihu.com/p/137512843
  • binlog redolog undolog

    2020-07-25 23:44:18
    innodb事务日志包括的redo logundo logredo log是物理日志,记录的是数据页的物理修改,它保证了事务的持久性。 redo log分为两部分:一个是内存中的日志缓冲(redo log buffer),该部分日志是容易丢失的。二是...
  • redo log 是物理日志,undo log 和 binlog 是逻辑日志 binlog二进制日志是server层的无论MySQL用什么引擎,都会有的,主要是左主从复制,时间点恢复使用 redo log重做日志是InnoDB存储引擎层的,用来保证事务安全 ...
  • 说说MySQL中的Redo log Undo log都在干啥

    千次阅读 2017-06-06 21:51:30
    阅读目录(Content) 1 undo 1.1 undo是啥1.2 undo参数1.3 undo空间管理 2 redo ...3.1 Undo + Redo事务的简化过程3.2 IO影响3.3 恢复  在数据库系统中,既有存放数据的文件,也有存放日志的
  • 吃透MySQL(十一):undolog redolog binlog原理详细介绍

    千次阅读 热门讨论 2021-03-06 12:09:19
    一,Undo log Undo:意为取消,以撤销操作为目的,返回指定某个状态的操作。 Undo Log:数据库事务提交之前,会将事务修改数据的镜像(即修改前的旧版本)存放到 undo 日志里,当事务回滚时,或者数据库奔溃时,可以...
  • Redo log Undo Log Bin log 作用 数据写入到mysql数据页的临时存储空间,磁盘上存储 事务回滚和MVCC 主从复制 类型 物理日志 逻辑日志 逻辑日志 幂等性 无幂等性 无幂等性 ...
  • Mysql日志-RedoLogUndoLog和BinLog

    千次阅读 2020-04-19 14:55:30
    一条查询语句的执行过程一般是经过连接器、...InnoDB是事务的存储引擎,其通过Force Log at Commit机制实现事务的持久性,即当事务提交(COMMIT)时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务的 CO...
  • 一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。 那么,一条更新语句的执行流程又是怎样的呢...这里的日志是指重做日志,在InnoDB存储引擎中,由两部分组成,即redo log
  • mysql binlog redolog undolog 日志概念说明binlogbinlog使用场景binlog刷盘时机binlog日志格式redo log为什么需要redo logredo log基本概念redo log记录形式redo log与binlog区别undo log 日志是 mysql 数据库的...
  • mysql innodb中MVCC理解和redo,undo log详解

    千次阅读 2019-02-16 12:44:56
    undo logredo log undo log redo log 简介 MVCC(Multiversion Concurrency Control),即多版本并发控制技术,它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是把...
  • binlog二进制日志是mysql-server层的...select如果没有特定加锁的话就是快照读,用到了undolog,而insert delete和update都是当前读,与这个日志关系不大。 redo log redo log在事务没有提交前,每一个修改操作都.
  • mysql的日志分为几大类:错误日志、查询日志、慢查询日志、事务日志(redo log和undolog)、二进制日志(binlog)。 binlog 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog...
  • ACID特性的实现原理ACID特性的实现原理1、背景(什么是事务)2、四大特性(ACID)2.1、原子性(Atomicity)2.1.1、定义2.1.2、undo log(回滚日志)2.2、持久性(Durability )2.2.1、定义2.2.2、redo log(重做日志)2.3...
  • redo log redo log是基于磁盘数据结构记录的日志,用于在db崩溃时恢复由未完成的事务写入的正确数据。在正常操作期间,redo log会对SQL语句或低级API调用产生的更改表数据的请求进行编码。在意外关闭之前没有完成...
  • 前面文章讲述了 MySQL 系统中常见的几种日志,其实还有事务相关日志 redo logundo log 没有介绍。相对于其他几种日志而言, redo logundo log 是更加神秘,难以观测的。本篇文章将主要介绍这两类事务日志的...
  • 分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(errorlog)、慢查询日志(slow query log)、一般查询日志(general log),中继日志(relay log)。 其中重做日志和回滚...
  • Undo Log,Redo Log和Binlog MySQL隔离级别,一致性视图,undo log,redo log和binglog MySQL索引结构,回表,最左前缀原则 Mysql相关 1、innoDB跟myisam的区别; 2、InnoDB的索引实现,唯一索引...说一下undolog, re
  • 所以为了避免这种情况,每次内存操作数据后,都在redolog中记录(顺序IO,写入速度快),以便之后恢复(redolog体积小,恢复速度快)。 2.3 在事务提交时,是两阶段提交(2PC)。如果SQL语句都执行成功,那么完成...
  • redologundolog这两个概念的区别

    千次阅读 2019-11-26 22:09:34
    InnoDB事务日志(redo log 和 undo log)详解 详细分析MySQL事务日志(redo log和undo log) redologundolog这两个概念的区别 数据库日志文件-- undo log 、redo log、 undo/redo log ...
  • mysql binlog、redo logundo log

    千次阅读 2020-02-07 17:14:02
    重做日志(redo log) 重做日志-作用 重做日志-内容 重做日志-什么时候产生 重做日志-什么时候释放 重做日志-对应的物理文件 重做日志-其他 回滚日志(undo log) 回滚日志-作用 回滚日志-内容 回滚日志-...
  • MySQL事务日志undo logredo log分析

    千次阅读 2019-04-20 17:16:37
    文章目录前言先聊聊undo log再聊聊redo log如何利用undo logredo log异常恢复?参考文章 前言 这两事务日志用来保证事务原子性、持久性的,undo log(回滚日志)提供回滚操作,保证原子性,redo log(重做日志)提供前...
  • redo logundo log篇 关于redo log 一,redo log的文件 二,redo log的写入 三,redo log的删除 四,查看redo log相关的配置 关于undo log 一,undo log的文件 二,undo log的写入 三,undo log的空间释放...
  • MySQL--buffer pool、redo logundo log、binlog

    千次阅读 多人点赞 2021-04-02 13:38:49
    同时为了保证MySQL宕机不丢失buffer pool中的数据,还引入了一个 叫做redo log的日志文件 。另外还有用于备份磁盘数据的bin log,用于事务回滚和MVCC的undo log等。对于日志文件则采取顺序读写的方式提高效率。 2.1 ...
  • 区分redolog和change buffer 前者为减少写操作,后者为减少读操作 前者是日志文件,后者主要是内存中 修改数据时,如果数据页已经在内存中,只写redolog。不在内存中,才会同时写change buffer和redolog

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,568
精华内容 13,827
关键字:

redologundolog