目录
binlog
介绍:
记录数据库执行的写入性操作,以二进制形式保存在磁盘中——>也就是说binlog是mysql的逻辑日志,由Server层记录
任何存储引擎的mysql数据库它都是用的binlog日志
-
逻辑日志:可以简单理解为记录的就是sql语句 。
-
物理日志:
mysql
数据最终是保存在数据页中的,物理日志记录的就是数据页变更 。
使用场景:
在实际应用中, binlog
的主要使用场景有两个,分别是 主从复制 和 数据恢复 。
-
主从复制 :在
Master
端开启binlog
,然后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据一致。 -
数据恢复 :通过使用
mysqlbinlog
工具来恢复数据。
刷盘时机(binlog什么时候刷盘到磁盘中)
对于 InnoDB
存储引擎而言,只有在事务提交时——>才会记录 biglog
,此时记录还在内存中,那么 binlog
是什么时候刷到磁盘中的呢?mysql
通过 sync_binlog
参数控制 biglog
的刷盘时机,取值范围是 0-N
-
0:不去强制要求,由系统自行判断何时写入磁盘;
-
1:每次
commit
的时候都要将binlog
写入磁盘; -
N:每N个事务,才会将
binlog
写入磁盘。——>减少了IO次数,提高了效率,但是风险增大
binlog日志格式
binlog
日志有三种格式,分别为 STATMENT
、 ROW
和 MIXED
。
目前Mysql日志默认格式是ROW,5.7.7之前STATEMENT
STATMENT
:基于SQL
语句的复制( statement-based replication, SBR
),每一条会修改数据的sql语句会记录到 binlog
中 。
-
优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO , 从而提高了性能;
-
缺点:在某些情况下会导致主从数据不一致,比如执行sysdate() 、 slepp() 等(毕竟只记录了修改数据的sql语句) 。
ROW
:基于行的复制(row-based replication, RBR
),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了
-
优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题,感觉还节约了内存 ;
-
缺点:会产生大量的日志,尤其是` alter table ` 的时候会让日志暴涨
MIXED
:基于STATMENT
和 ROW
两种模式的混合复制( mixed-based replication, MBR
),一般的复制使用 STATEMENT
模式保存 binlog
,对于 STATEMENT
模式无法复制的操作使用 ROW
模式保存 binlog
redo log
介绍:
为什么使用redolog?这就和我们数据库事务中的持久性有关——>意思:只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态
场景——>数据库宕机,尚有数据未写入磁盘时的情况,InnoDB就会读取我们的redolog,这也就是为什么MyISAM不支持持久性的原因
(45条消息) SQL高级_Fairy要carry的博客-CSDN博客
问:mysql如何保证数据一致性的?
最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题
-
因为
Innodb
是以页
为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了! -
一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!
因此 mysql
设计了 redo log
, 具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)
基本概念
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 。 |
redolog和binlog的区别
redo log | binlog | |
---|---|---|
文件大小 | redo log 的大小是固定的。 | binlog 可通过配置参数 max_binlog_size 设置每个binlog 文件的大小。 |
实现方式 | redo log 是 InnoDB 引擎层实现的,并不是所有引擎都有。 | binlog 是 Server 层实现的,所有引擎都可以使用 binlog 日志 |
记录方cd式 | redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。 | binlog通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上 |
适用场景 | redo log 适用于崩溃恢复(crash-safe) | binlog 适用于主从复制和数据恢复 |
redolog的作用
redolog是用来做崩溃恢复使用的,这种崩溃恢复不需要我们人为的参与,MySQL自己内部自己实现了这种崩溃恢复的功能,我们只管享受这种功能给我们带来的服务即可,这种服务给我们的感受就是:MySQL数据库异常宕机的时候,重启服务之后,数据库中之前提交的记录都不会丢失数据仍然可以正常恢复,不管这种提交的记录是否已经更到具体的表所对应的磁盘page也中。
MySQL内部在实现崩溃恢复的功能时,到底是如何实现的呢?
当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log里面(redolog日志是循环追加写的,属于顺序IO,记录的速度在某些程度上可以和内存相媲美),并更新内存,这个时候更新就算完成了(此时数据就在redolog中),MySQL在崩溃恢复的时候,会从记下来的redolog中找到已经提交的更改内容,所以不会担心MySQL异常重启后,数据的丢失
undo log
介绍
数据库事务四大特性中有一个是 原子性 ,具体来说就是 原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况
。实际上, 原子性 底层就是通过 undo log
实现的。undo log
主要记录了数据的逻辑变化,比如一条 INSERT
语句,对应一条 INSERT
的 undo log
,对于每个 UPDATE
语句,对应一条相反的 UPDATE
的 undo log
,这样在发生错误时,就能回滚到事务之前的数据状态。同时, undo log
也是 MVCC
(多版本并发读控制)实现的关键,这部分内容在 面试中的老大难-mysql事务和锁,一次性讲清楚!中有介绍,不再赘述。
场景:
根据当前版本的数据生成undolog,保存事务发生前的这个数据的一个版本,可以用于回滚——>例如seata中的AT模式,防止了脏写