bin log,redo log以及undo log详解_xxx_520s的博客-程序员信息网_binlog undolog

技术标签: mysql  数据库  sql  

1 bin log

1.1 定义

bin log应该说是Mysql里最核心的日志,是MySQL数据库级别的文件,记录对MySQL数据库各种引擎下执行修改的所有操作(包括DDL和DML语句),不会记录select和show语句,主要用于恢复数据库和同步数据库(主从同步)。

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。

这三种模式需要注意的是:使用 row 格式的 binlog 时,在进行数据同步或恢复的时候不一致的问题更容易被发现,因为它是基于数据行记录的。而使用 mixed 或者 statement 格式的 binlog 时,很多事务操作都是基于SQL逻辑记录,我们都知道一个SQL在不同的时间点执行它们产生的数据变化和影响是不一样的,所以这种情况下,数据同步或恢复的时候就容易出现不一致的情况。

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是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 binlog可以替换redo log用于宕机后的数据恢复吗?

  1. 最核心的一点就是redo log记录的数据变更粒度和binlog的数据变更粒度是不一样的,也正因为这个binlog是没有进行崩溃恢复事务数据的能力的。

  2. 以修改数据为例,binlog 是以表为记录主体,在ROW模式下,binlog保存的表的每行变更记录
    比如update tb_user set age =18 where name =‘赵白’ ,如果这条语句修改了三条记录的话,那么binlog记录就是

UPDATE `db_test`.`tb_user` WHERE @1=5 @2='赵白' @3=91 @4='1543571201' SET  @1=5 @2='赵白' @3=18 @4='1543571201'
UPDATE `db_test`.`tb_user` WHERE @1=6 @2='赵白' @3=91 @4='1543571201' SET  @1=5 @2='赵白' @3=18 @4='1543571201'
UPDATE `db_test`.`tb_user` WHERE @1=7 @2='赵白' @3=91 @4='1543571201' SET  @1=5 @2='赵白' @3=18 @4='1543571201'redo
  1. log则是记录着磁盘数据的变更日志,以磁盘的最小单位“页”来进行记录。
    上面的修改语句,在redo
    log里面记录得可能就是下面的形式。

把表空间10、页号5、偏移量为10处的值更新为18。

把表空间11、页号1、偏移量为2处的值更新为18。

把表空间12、页号2、偏移量为9处的值更新为18。

当我们把数据从内存保存到磁盘的过程中,Mysql是以页为单位进行刷盘的,这里的页并不是磁盘的页,而是Mysql自己的单位,Mysql里的一页数据单位为16K,所以在刷盘的过程中需要把数据刷新到磁盘的多个扇区中去。 而把16K数据刷到磁盘的每个扇区里这个过程是无法保证原子性的,也就意味着Mysql把数据从内存刷到磁盘的过程中,如果数据库宕机,那么就可能会造成一步分数据成功,一部分数据失败的结果。而这个时候通过binlog这种级别的日志是无法恢复的,一个update可能更改了多个磁盘区域的数据,如果根据SQL语句回滚,那么势必会让那些已经刷盘成功的数据造成数据不一致。所以这个时候还是得需要通过redo log这种记录到磁盘数据级别的日志进行数据恢复。

  1. 另一个很重要的点就是并不知道 bin log中的sql语句是否执行成功,因为没有事务是否提交成功的状态记录字段

2.3 redo log刷盘时机

  1. redo lo占用的空间是一定的,并不会无线增大(可以通过参数设置),写入的时候是进顺序写的,所以写入的性能比较高。当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。

  2. 在写入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

除了记录redo log外,当进行数据修改时还会记录undo log,undo log用于数据的撤回操作,它保留了记录修改前的内容。通过undo log可以实现事务回滚,并且可以根据undo log回溯到某个特定的版本的数据,实现MVCC。

注释:redo log 和 undo log都是属于事务日志

4 bin log和redo log有什么区别?

  1. bin log会记录所有日志记录,包括InnoDB、MyISAM等存储引擎的日志;redo log只记录innoDB自身的事务日志。
  2. bin log主要用于数据库的 主从复制 以及数据恢复工作(比如恢复到数据库的某一个历史版本),redo log 主要用于发生故障后,让所有数据恢复到发生故障之前的状态
  3. bin log是逻辑日志,记录的是SQL语句;redo log是物理日志,记录的数据格式是 “在某个数据页上做了什么修改”。
  4. bin log的日志空间是二进制流式的缓冲区,写完一个缓冲区后,不会覆盖之前的内容,而是重开一个缓冲区,继续写入日志;
    而redo log的日志空间大小是固定的,通过循环写入的方式将日志写入磁盘,一旦没有空闲空间,则会采用覆盖的方式,覆盖的之前的内容
  5. bin log只在事务提交前被写入一次磁盘(MySQL 5.7.7之后版本的默认保存方式),一个事务只写一次;而对于redo log,在事务开始时会写入一次磁盘,提交redo log为prepare状态,事务提交后又会写入一次磁盘,提交redo log 为commit状态

5 redo log 和 undo log的区别

  1. 目的不同:redo log主要是用于发生故障时的数据恢复操作,将数据恢复到故障发生前的状态,而undo log主要用于事务的回滚,将数据恢复为事务发生前的状态

6 redo、undo、binlog的生成流程与崩溃恢复

当我们执行update user_info set name =“李四” where id=1 的时候大致流程如下:

  1. 从磁盘读取到id=1的记录,放到内存。
  2. 记录undo log 日志。
  3. 记录redo log (预提交状态)
  4. 修改内存中的记录。
  5. 记录binlog
  6. 提交事务,写入redo log (commit状态)

https://pic4.zhimg.com/v2-346d0dcc7b5e7a3295357e099ad54f7b_b.jpg

我们根据上面的流程来看,如果在上面的某一个阶段数据库崩溃,如何恢复数据。

1、在第一步、第二步、第三步执行时据库崩溃:因为这个时候数据还没有发生任何变化,所以没有任何影响,不需要做任何操作。

2、在第四步修改内存中的记录时数据库崩溃:因为此时事务没有commit,所以不管有没有将修改的数据写回磁盘,这里都要进行数据回滚,所以这里会通过undo log进行数据回滚。

3、第五步写入binlog时数据库崩溃:这里和第四步一样的逻辑,此时事务没有commit,所以这里要进行数据回滚,会通过undo log进行数据回滚。

4、执行第六步事务提交时数据库崩溃:如果数据库在这个阶段崩溃,那其实事务还是没有提交成功,但是这里并不能像之前一样对数据进行回滚,因为在提交事务前,binlog可能成功写入磁盘了,所以这里要根据两种情况来做决定。

  • 如果binlog存在事务记录:那么就"认为"事务已经提交了,这里可以根据redo log对数据进行重做。其实你应该有疑问,其实这个阶段发生崩溃了,最终的事务是没提交成功的,这里应该对数据进行回滚。 这里主要的一个考虑是因为binlog已经成功写入了,而binlog写入后,那么依赖于binlog的其它扩展业务(比如:从库已经同步了日志进行数据的变更)数据就已经产生了,如果这里进行数据回滚,那么势必就会造成主从数据的不一致。

  • 另外一种情况就 是binlog不存在事务记录,那么这种情况事务还未提交成功,所以会对数据进行回滚。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yxg520s/article/details/122242793

智能推荐

文本文件编码格式_xzy1990_25的博客-程序员信息网

文本文件的编码格式有:ANSI;Unicode:

python 通过logging记录INFO和DEBUG记录_蓝鲸123的博客-程序员信息网

import shutilimport osfrom itertools import cycleimport logging.configfrom datetime import datetimeimport jsonfrom bokeh.io import output_file, save, showfrom bokeh.plotting import figurefrom ...

openstack 创建实例时错误总结_maibm的博客-程序员信息网_openstack创建实例状态错误

1、网络错误Management网络,Provider网络,一开始不太理解一开始按照官网的建议部署了双网卡,网卡一192.168.0.11/24(桥接模式) ,网卡二按官网不配地址(nat模式)openstack subnet create --network provider \ --allocation-pool start=192.168.0.200,end=192.168.0....

实型变量(浮点型变量)、字符型数据、字符串常量(变量)、字符常量(变量)_weixin_43671182的博客-程序员信息网_实型变量

实型变量1、实型变量的舍入误差因为内存分配给实型变量的空间是有限的,所以当存储数据时,就会遇到舍入的问题,我们举个例子void main(){float a,b;a=123456.789e5;b=a+20;printf("%f\n",a);printf("%f\n",b);}这个时候出现的结果就是这样,又因为a本身已经溢出了,加上20之后也是没产生变化的。字符型数据...

【笔记】COA课内实验-MMX指令集_Little_Fall的博客-程序员信息网

前言参考资料关于BMP文件格式的详解原理学习1. BMP-DIB位图编码什么是BMPBMP(全称Bitmap,位图)是Windows中的标准图像文件格式,其中有一类叫做设备无关位图(DIB)。BMP文件存储数据时,图像的扫描方式是按从下到上,从左到右的顺序。BMP文件按深度分为多类,如16色,256色,24位,32位,以下均按32位位图。BMP文件编码依次为:位图文件头+位图信...

随便推点

弘辽科技:成立仅5年的拼多多是如何一步步“紧逼”阿里的?_普通网友的博客-程序员信息网

原标题《弘辽科技:成立仅5年的拼多多是如何一步步“紧逼”阿里的?》成立仅仅5年的拼多多,不经意间已经成长为一家万亿公司。2020年11月12日,拼多多发布的第三季度财报显示,公司Q3净利润超4.6亿元,首次实现季度盈利,期间营收为142亿,同比增长89%。受此消息影响,拼多多股价随后快速上涨,达历史最高点156美元,公司市值约为1.2万亿人民币。上市仅两年,拼多多就成为了股价接近翻10倍的超级明星股,崛起速度令人咋舌。其创始人黄峥也成为了继马云、马化腾、农夫山泉创始人钟睒睒后,中国排名第四的富豪

__import__ 与动态加载 python module_JackLiu16的博客-程序员信息网

本文介绍 python module 的动态加载,我们有时希望从配置文件等地获取要被动态加载的 module,但是所读取的配置项通常为字符串类型,无法用 import 加载,例如: 1 2 3 4 5 6 >>> import 'os' File "<stdin>", line 1 ...

ask信号调制matlab,基于Matlab的ASK数字调制系统仿真_薛志荣的博客-程序员信息网

基于Matlab的ASK数字调制系统仿真摘要:“幅移键控”又称为“振幅键控”,记为ASK。也有称为“开关键控”(通断键控)的,所以又记作OOK信号。ASK是一种相对简单的调制方式。幅移键控(ASK)相当于模拟信号中的调幅,只不过与载频信号相乘的是二进制数码而已。幅移就是把频率、相位作为常量,而把振幅作为变量,信息比特是通过载波的幅度来传递的。二进制振幅键控(2ASK),由于调制信号只有0或1两个电...

c++const关键字_h595636059的博客-程序员信息网

看到const 关键字,C++程序员首先想到的可能是const 常量。这可不是良好的条件反射。如果只知道用const 定义常量,那么相当于把火药仅用于制作鞭炮。const 更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。

自动驾驶芯片之——FPGA和ASIC介绍_喜欢打酱油的老鸟的博客-程序员信息网

https://www.toutiao.com/a6630584455218070019/ 2018-12-03 10:14:06当前阶段,GPU 配合 CPU 仍然是 AI 芯片的主流,而后随着视觉、语音、深度学习的算法在 FPGA以及 ASIC芯片上的不断优化,此两者也将逐步占有更多的市场份额,从而与GPU达成长期共存的局面。从长远看,人工智能类脑神经芯片是发展的路径和方向。本文主...

UI设计入门:五种基本APP界面类型【萧蕊冰】_萧蕊冰冰的博客-程序员信息网_ui有哪些界面

今天这篇是一个UI设计入门:五种基本APP界面类型的欣赏。随着互联网的发展和智能手机的普及,移动应用成了大家最热爱的宠儿,许多移动APP也会根据用户的需求来随时替换本身的UI设计。本篇UI设计入门分享的是app界面的设计赏析。界面作为我们认识APP的第一道门槛,是APP的“面子”,更是不可忽视的一项重点设计,为了建立有效的UI,设计师需要根据移动端APP本身的特性和当下趋势,作出不一样的改变。但当今设计趋势瞬息万变,在没有统一标准的设计规则之下,紧跟设计趋势,才能保证UI对用户的吸引力常在。下面介绍

推荐文章

热门文章

相关标签