共计 3515 个字符,预计需要花费 9 分钟才能阅读完成。
转自:陈添明 \
链接: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 logfile
)。
mysql
每执行一条 DML
语句,先将记录写入 redo log buffer
,后续某个工夫点再一次性将多个操作记录写到 redo log file
。这种 先写日志,再写磁盘 的技术就是 MySQL
里常常说到的 WAL(Write-Ahead Logging)
技术。
在计算机操作系统中,用户空间 (user space
) 下的缓冲区数据个别状况下是无奈间接写入磁盘的,两头必须通过操作系统内核空间 (kernel space
) 缓冲区(OS Buffer
)。
因而,redo log buffer
写入 redo logfile
实际上是先写入 OS Buffer
,而后再通过零碎调用 fsync()
将其刷到 redo log file
中,过程如下:
mysql
反对三种将 redo log buffer
写入 redo log file
的机会,能够通过 innodb_flush_log_at_trx_commit
参数配置,各参数值含意如下:
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 区别
由 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
(多版本并发管制)实现的要害。
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿(2021 最新版)
2. 别在再满屏的 if/ else 了,试试策略模式,真香!!
3. 卧槽!Java 中的 xx ≠ null 是什么新语法?
4.Spring Boot 2.5 重磅公布,光明模式太炸了!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!