共计 4391 个字符,预计需要花费 11 分钟才能阅读完成。
起源:https://juejin.im/post/686025…
作者:六点半起床
日志是 mysql
数据库的重要组成部分,记录着数据库运行期间各种状态信息。 mysql
日志次要包含谬误日志、查问日志、慢查问日志、事务日志、二进制日志几大类。作为开发,咱们重点须要关注的是二进制日志 ( binlog
) 和事务日志(包含 redo log
和 undo log
),本文接下来会具体介绍这三种日志。
binlog
binlog
用于记录数据库执行的写入性操作 (不包含查问) 信息,以二进制的模式保留在磁盘中。 binlog
是 mysql
的逻辑日志,并且由 Server
层进行记录,应用任何存储引擎的 mysql
数据库都会记录 binlog
日志。
- 逻辑日志:能够简略了解为记录的就是 sql 语句。
- 物理日志:
mysql
数据最终是保留在数据页中的,物理日志记录的就是数据页变更。
binlog
是通过追加的形式进行写入的,能够通过 max_binlog_size
参数设置每个 binlog
文件的大小,当文件大小达到给定值之后,会生成新的文件来保留日志。
binlog 应用场景
在理论利用中, binlog
的次要应用场景有两个,别离是 主从复制 和 数据恢复。
- 主从复制:在
Master
端开启binlog
,而后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据统一。 - 数据恢复:通过应用
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
日志有三种格局,别离为 STATMENT
、 ROW
和 MIXED
。
在
MySQL 5.7.7
之前,默认的格局是STATEMENT
,MySQL 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
:基于STATMENT
和ROW
两种模式的混合复制(mixed-based replication, MBR
),个别的复制应用STATEMENT
模式保留binlog
,对于STATEMENT
模式无奈复制的操作应用ROW
模式保留binlog
redo log
为什么须要 redo log
咱们都晓得,事务的四大个性外面有一个是 持久性 ,具体来说就是
只有事务提交胜利,那么对数据库做的批改就被永恒保留下来了,不可能因为任何起因再回到原来的状态 。那么 mysql
是如何保障一致性的呢?最简略的做法是在每次事务提交的时候,将该事务波及批改的数据页全副刷新到磁盘中。然而这么做会有重大的性能问题,次要体现在两个方面:
- 因为
Innodb
是以页
为单位进行磁盘交互的,而一个事务很可能只批改一个数据页外面的几个字节,这个时候将残缺的数据页刷到磁盘的话,太浪费资源了! - 一个事务可能波及批改多个数据页,并且这些数据页在物理上并不间断,应用随机 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 pos
到 check point
之间的局部是 redo log
空着的局部,用于记录新的记录; check point
到 write 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 log | binlog | |
---|---|---|
文件大小 | redo log 的大小是固定的。 |
binlog 可通过配置参数 max_binlog_size 设置每个 binlog 文件的大小。 |
实现形式 | redo log 是 InnoDB 引擎层实现的,并不是所有引擎都有。 |
binlog 是 Server 层实现的,所有引擎都能够应用 binlog 日志 |
记录形式 | redo log 采纳循环写的形式记录,当写到结尾时,会回到结尾循环写日志。 | binlog 通过追加的形式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上 |
实用场景 | redo log 实用于解体复原(crash-safe) |
binlog 实用于主从复制和数据恢复 |
由 binlog
和 redo log
的区别可知: binlog
日志只用于归档,只依附 binlog
是没有 `
crash-safe 能力的。但只有
redo log 也不行,因为
redo log 是
InnoDB `
特有的,且日志上的记录落盘后会被笼罩掉。因而须要 binlog
和 redo log
二者同时记录,能力保障当数据库产生宕机重启时,数据不会失落。
undo log
数据库事务四大个性中有一个是 原子性 ,具体来说就是 原子性是指对数据库的一系列操作,要么全副胜利,要么全副失败,不可能呈现局部胜利的状况
。实际上, 原子性 底层就是通过 undo log
实现的。 undo log
次要记录了数据的逻辑变动,比方一条 ` INSERT 语句,对应一条
DELETE 的
undo log ,对于每个
UPDATE 语句,对应一条相同的
UPDATE 的
undo log ,这样在产生谬误时,就能回滚到事务之前的数据状态。同时,
undo log 也是
MVCC `
(多版本并发管制) 实现的要害,这部分内容在 [面试中的老大难 -mysql 事务和锁,一次性讲清楚!
](https://juejin.im/post/685512… 中有介绍,不再赘述。
参考
- juejin.im/post/684490…
- www.cnblogs.com/f-ck-need-u…
- www.cnblogs.com/ivy-zheng/p…
- yq.aliyun.com/articles/59…
- www.jianshu.com/p/5af73b203…
- www.jianshu.com/p/20e10ed72…
学习材料分享
12 套 微服务、Spring Boot、Spring Cloud 核心技术材料,这是局部材料目录:
- Spring Security 认证与受权
- Spring Boot 我的项目实战(中小型互联网公司后盾服务架构与运维架构)
- Spring Boot 我的项目实战(企业权限治理我的项目))
- Spring Cloud 微服务架构我的项目实战(分布式事务解决方案)
- …
公众号后盾回复
arch028
获取材料::