bin log,redo log以及undo log详解
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用于宕机后的数据恢复吗?
最核心的一点就是redo log记录的数据变更粒度和binlog的数据变更粒度是不一样的,也正因为这个binlog是没有进行崩溃恢复事务数据的能力的。
以修改数据为例,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
- 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这种记录到磁盘数据级别的日志进行数据恢复。
- 另一个很重要的点就是并不知道 bin log中的sql语句是否执行成功,因为没有事务是否提交成功的状态记录字段
2.3 redo log刷盘时机
redo lo占用的空间是一定的,并不会无线增大(可以通过参数设置),写入的时候是进顺序写的,所以写入的性能比较高。当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。
在写入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。
除了上面几种机制外,还有其它两种情况会把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有什么区别?
- bin log会记录所有日志记录,包括InnoDB、MyISAM等存储引擎的日志;redo log只记录innoDB自身的事务日志。
- bin log主要用于数据库的 主从复制 以及数据恢复工作(比如恢复到数据库的某一个历史版本),redo log 主要用于发生故障后,让所有数据恢复到发生故障之前的状态
- bin log是逻辑日志,记录的是SQL语句;redo log是物理日志,记录的数据格式是 “在某个数据页上做了什么修改”。
- bin log的日志空间是二进制流式的缓冲区,写完一个缓冲区后,不会覆盖之前的内容,而是重开一个缓冲区,继续写入日志;
而redo log的日志空间大小是固定的,通过循环写入的方式将日志写入磁盘,一旦没有空闲空间,则会采用覆盖的方式,覆盖的之前的内容 - bin log只在事务提交前被写入一次磁盘(MySQL 5.7.7之后版本的默认保存方式),一个事务只写一次;而对于redo log,在事务开始时会写入一次磁盘,提交redo log为prepare状态,事务提交后又会写入一次磁盘,提交redo log 为commit状态
5 redo log 和 undo log的区别
- 目的不同:redo log主要是用于发生故障时的数据恢复操作,将数据恢复到故障发生前的状态,而undo log主要用于事务的回滚,将数据恢复为事务发生前的状态
6 redo、undo、binlog的生成流程与崩溃恢复
当我们执行update user_info set name =“李四” where id=1 的时候大致流程如下:
- 从磁盘读取到id=1的记录,放到内存。
- 记录undo log 日志。
- 记录redo log (预提交状态)
- 修改内存中的记录。
- 记录binlog
- 提交事务,写入redo log (commit状态)
我们根据上面的流程来看,如果在上面的某一个阶段数据库崩溃,如何恢复数据。
1、在第一步、第二步、第三步执行时据库崩溃:因为这个时候数据还没有发生任何变化,所以没有任何影响,不需要做任何操作。
2、在第四步修改内存中的记录时数据库崩溃:因为此时事务没有commit,所以不管有没有将修改的数据写回磁盘,这里都要进行数据回滚,所以这里会通过undo log进行数据回滚。
3、第五步写入binlog时数据库崩溃:这里和第四步一样的逻辑,此时事务没有commit,所以这里要进行数据回滚,会通过undo log进行数据回滚。
4、执行第六步事务提交时数据库崩溃:如果数据库在这个阶段崩溃,那其实事务还是没有提交成功,但是这里并不能像之前一样对数据进行回滚,因为在提交事务前,binlog可能成功写入磁盘了,所以这里要根据两种情况来做决定。
如果binlog存在事务记录:那么就"认为"事务已经提交了,这里可以根据redo log对数据进行重做。其实你应该有疑问,其实这个阶段发生崩溃了,最终的事务是没提交成功的,这里应该对数据进行回滚。 这里主要的一个考虑是因为binlog已经成功写入了,而binlog写入后,那么依赖于binlog的其它扩展业务(比如:从库已经同步了日志进行数据的变更)数据就已经产生了,如果这里进行数据回滚,那么势必就会造成主从数据的不一致。
另外一种情况就 是binlog不存在事务记录,那么这种情况事务还未提交成功,所以会对数据进行回滚。
bin log,redo log以及undo log详解相关推荐
- 【MySql进阶】undo日志详解:undo日志结构、undo日志链表、回滚段、undo log原理
undo日志 本文为阅读<MySql是怎样运行的>的笔记,供大家参考. 文章目录 undo日志 概述 undo日志数据结构 insert 对应的undo log delete 对应的und ...
- 容器编排技术 -- Kubernetes kubectl rollout undo 命令详解
容器编排技术 -- Kubernetes kubectl rollout undo 命令详解 1 kubectl rollout undo 2 语法 3 示例 4 Flags kubectl roll ...
- linux bin fuser,Linux中fuser命令用法详解
描述: fuser可以显示出当前哪个程序在使用磁盘上的某个文件.挂载点.甚至网络端口,并给出程序进程的详细信息. fuser显示使用指定文件或者文件系统的进程ID. 默认情况下每个文件名后面跟一个字母 ...
- 蓝牙btsnoop log,HFP协议连接流程详解,以及RFCOMM连接和常用AT指令
HFP(Hands-Free):蓝牙免提协议,两个角色AG,HF端,AG端通常是手机设备,HF免提端一般为耳机车载等,hfp的连接首先要进行SDP,然后建立RFCOMM,然后SLC连接完成,HFP正式 ...
- oracle segment undo_Oracle undo管理详解
一.What isundo Every Oracle database must have a method of maintaining information that is used to ro ...
- undo系统参数详解
查看与undo相关的系统参数 1.undo_management 有两个参数值:auto.manual(默认) manual:系统启动后使用rollback segment存储undo信息: auto ...
- 【图文详解】MySQL事务日志 Redo log(重做) 和 Undo log(撤销)
InnoDB Architecture https://dev.mysql.com/doc/refman/5.6/en/innodb-architecture.html 我们都知道数据库有四大属性AC ...
- 一文聊透binlog、redo log、undo log
今日推荐 Web登录很简单?开玩笑!知乎热问:国家何时整治程序员的高薪现象?太可怕了!注解+反射优雅的实现Excel导入导出(通用版)Fluent Mybatis 牛逼!Nginx 常用配置清单这玩意 ...
- MYSQL专题-MySQL三大日志binlog、redo log和undo log
日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括重做日志(redo log).回滚日志(undo log).二进制日志(bin log).错误日志(err ...
- 【转】【MySQL】运行原理(四):重做日志(redo log),回滚日志(undo log),二进制日志(binlog)
MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...
最新文章
- jmeter+mysql+set_Jmeter中如何进行对数据库压测(上)
- 关系数据库和nosql
- 《SpringBoot揭秘:快速构建微服务体系》—第3章3.5节本章小结
- 一起来做个免登录资源导航小程序!
- 网络管理不简单 需化被动为主动
- (25)二分频verilog与VHDL编码(学无止境)
- 如何在ASP.NET Core中编写自定义日志记录提供程序
- 全网首发:JDK绘制文字:二、绘制句柄的初始化流程
- F - Firetrucks Are Red
- 蓝桥杯 基础练习 特殊回文数 JAVA
- 计算机怎么连接手机网络,电脑怎么连接手机的热点上网?
- windows系统c++/VS2019编译gRPC
- php file_get_contents 失效,phpfile_get_contents返回空无效解决办法_PHP教程
- UVM factory机制源码探微
- Android开发本地及网络Mp3音乐播放器(十五)网络音乐及歌词下载功能实现
- 开关数字方格哥德巴赫猜想自我数积木
- 一条命令轻松绘制CNS顶级配图-ggpubr
- hive插入表数据以及出现问题的解决
- plc secs通讯协议_SECS/GEM通信协议学习笔记
- C语言给出点坐标进行克里金插值,Arcgis笔记之克里金插值——求助surfer8.0
热门文章
- 论分布式数据库架构的“存”与“算”
- c语言入门经典18个程序,C语言入门经典
- 群聊系统项目(基于TCP、UDP实现)
- (python)班级身高排序
- 说“快乐”还是“安康”?如何在不抬杠的情况下用AI搞定这问题
- php中h语言是什么意思,stdio.h是什么意思?
- 本人40多岁大龄码农,国内已经没人要了,被优化后去日本工作,一人上班轻松养活三口之家!...
- vue.config.js配置完代理还是提示跨域?
- 数据库模糊查询和范围查询
- 40年未有之大变局,小家电江湖谁主风云