日志
-
undo log(回滚日志)
- Innodb 存储引擎层生成
- 实现了事务中的原子性,主要用于事务回滚和 MVCC。
-
redo log(重做日志)
- Innodb 存储引擎层生成
- 实现了事务中的持久性,主要用于掉电等故障恢复;
-
binlog (归档日志)
-
Server 层生成
-
用于数据备份和主从复制;
-
Undo log
Why?
事务执行过程中还没提交之前崩溃或者失败,怎么回滚到事务之前的状态?
How?
在改数据之前记录一下之前的数据即可,崩溃后直接根据原来的数据回滚。
undo log(回滚日志)作用:
- 实现事务回滚,保证了事务的原子性(Atomicity)
- ReadView + undo log 实现 MVCC(多版本并发控制)。
流程:
-
对一条记录进行操作(修改、删除、新增)时,把回滚时需要的信息都记录到 undo log 里:
- 插入:把这条记录的主键值记下来,回滚时把主键值对应的记录删除;
- 删除:把这条记录中的内容都记下来,回滚时把插入到表中;
- 更新:把列的旧值记下来,回滚时把这些列更新为旧值。
-
回滚时:
- 读取 undo log 里的数据,然后做原先相反操作。
-
组成:
-
trx_id:该记录是被哪个事务修改的;
-
roll_pointer:将这些 undo log 串成一个版本链;
-
undo log 是如何刷盘(持久化到磁盘)的?
undo log 和数据页的刷盘策略是一样的,都需要通过 redo log 保证持久化。
buffer pool 中有 undo 页,对 undo 页的修改也都会记录到 redo log。redo log 会每秒刷盘,提交事务时也会刷盘,数据页和 undo 页都是靠这个机制保证持久化的。
Redo log
Why?
数据写入都是先记录在Buffer Pool,没来得及同步的数据,突然断电直接丢失
How?
追加顺序写入的形式,快速记录在磁盘。
WAL (Write-Ahead Logging):MySQL 的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。
redo log
-
作用:
- crash-safe:数据库异常重启,之前已提交的记录都不会丢失
- 保证了事务的持久性
- 写操作从磁盘的「随机写」变成了「顺序写」提升性能
-
物理日志,记录了某个数据页做了什么修改:
- 对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新
-
事务提交时,只要先将 redo log 持久化到磁盘即可,无需写回脏数据页
-
崩溃重启后根据 redo log ,将所有数据恢复到最新的状态。
被修改 Undo 页面,需要记录对应 redo log 吗?
需要的。
开启事务后,InnoDB 层更新记录前,首先要记录相应的 undo log,如果是更新操作,需要把被更新的列的旧值记下来,也就是要生成一条 undo log,undo log 会写入 Buffer Pool 中的 Undo 页面。
不过,在内存修改该 Undo 页面后,需要记录对应的 redo log。
redo log 和 undo log 区别
-
redo log 记录事务「完成后」的数据状态,记录的是更新之后的值;
-
undo log 记录事务「开始前」的数据状态,记录的是更新之前的值;
redo log 写入磁盘时机?
-
redo log buffer:redo log 的缓存,每当产生一条 redo log 时,会先写入到 redo log buffer,后续在持久化到磁盘
- innodb_log_Buffer_size:默认大小 16 MB
-
刷盘时机:
- MySQL 正常关闭;
- redo log buffer 写入量大于最大空间的一半时,会触发落盘;
- InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。
- 每次事务结束时,选择落盘时机:innodb_flush_log_at_trx_commit
-
innodb_flush_log_at_trx_commit:
-
0:redo log buffer在事务提交时不主动触发写入磁盘。
- InnoDB 的后台线程每隔 1 秒write()+fsync()
- 会丢1s数据,最不安全,但是性能最高
-
1:每次事务提交时都将redo log 直接持久化到磁盘。
- 适合安全性要求高的场景
-
2:每次事务提交时都只把redo log 写到 redo log 文件(操作系统的文件缓存Page Cache)。
-
InnoDB 的后台线程每隔 1 秒fsync()
-
MySQL崩溃没事,操作系统崩溃就完蛋,相当于折中方案
-
-
redo log 文件
Redo log 有 1 个重做日志文件组(redo log Group),由2 个 redo log 文件组成:ib_logfile0 和 ib_logfile1
-
每个 redo log File 的大小是固定以循环写的方式工作的,从头开始写,写到末尾就又回到开头,相当于一个环形。
- 先写 ib_logfile0 文件,被写满切换至 ib_logfile1 文件,以此类推。
-
当脏页写回磁盘,redolog 空间可释放
- write pos:当前记录写到的位置
- checkpoint:当前要擦除的位置
-
Redo log满时,阻塞新的更新操作,进行刷盘
- 红色部分:记录新的更新操作;
- 蓝色部分:待落盘的脏数据页记录;
Bin log
binlog:记录所有数据库表结构变更和表数据修改的日志,事务提交时将执行过程中产生的所有 binlog 统一写入 binlog 文件。
- MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。
redo log 和 binlog 区别
-
适用对象不同:
- binlog:MySQL 的 Server 层,所有存储引擎都可以使用;
- redo log:Innodb 存储引擎实现的日志;
-
文件格式不同:
-
binlog:3 种格式类型:😡
- STATEMENT(默认):每一条修改数据的 SQL 都会被记录到 binlog 中(相当于记录了逻辑操作,所以针对这种格式, binlog 可以称为逻辑日志),主从复制中 slave 端再根据 SQL 语句重现。但 STATEMENT 有动态函数的问题,比如你用了 uuid 或者 now 这些函数,你在主库上执行的结果并不是你在从库执行的结果,这种随时在变的函数会导致复制的数据不一致;
- ROW:记录行数据最终被修改成什么样了(这种格式的日志,就不能称为逻辑日志了),不会出现 STATEMENT 下动态函数的问题。但 ROW 的缺点是每行数据的变化结果都会被记录,比如执行批量 update 语句,更新多少行数据就会产生多少条记录,使 binlog 文件过大,而在 STATEMENT 格式下只会记录一个 update 语句而已;
- MIXED:包含了 STATEMENT 和 ROW 模式,它会根据不同的情况自动使用 ROW 模式和 STATEMENT 模式;
-
-
redo log:物理日志,记录的是在某个数据页做了什么修改,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新;
-
写入方式不同:
- binlog:追加写,写满一个文件,就创建一个新的文件继续写,保存全量的日志。
- redo log:循环写,日志空间大小是固定,全部写满就从头开始,保存未被刷入磁盘的脏页日志。
-
用途不同:
- binlog:备份恢复、主从复制;
- redo log:掉电等故障恢复。
binlog刷盘时机
事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。一个事务的 binlog 是不能被拆开,防止从库破坏事务。
-
binlog cache:每个线程分配了一片内存用于缓冲 binlog
- binlog_cache_size,超过大小要暂存在磁盘
-
write:把日志写入到 binlog 文件(系统缓存)
-
fsync:将数据持久化到磁盘
-
sync_binlog:控制数据库的 binlog 刷到磁盘上的频率
-
0:每次提交事务都只 write,不 fsync。(默认)
- 后续交由操作系统决定何时将数据持久化到磁盘;
-
1:每次提交事务都会 write,然后马上执行 fsync;
-
N(N>1):每次提交事务都 write累积 N 个事务后fsync。
-
通常100~1000
-
-
主从复制原理
3 个阶段:
-
写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。
-
同步 Binlog:从库创建 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog 日志,再把 binlog 信息写入 relay log 的中继日志里,再返回给主库“复制成功”的响应。
-
回放 Binlog:从库读 relay log,回放 binlog 更新存储引擎中的数据,最终实现主从的数据一致性。
-
一个主库一般跟 2~3 个从库
- 从库变多主库资源消耗大
主从复制模型
-
同步复制:主库提交事务等待所有从库复制成功才返回
- 性能很差、可用性低
-
异步复制(默认模型):主库提交事务不会等待同步从库,就返回结果。
- 一旦主库宕机,数据就会发生丢失。
-
半同步复制:只要一部分复制成功响应回来就行
- 比如一主二从,只要数据成功复制到任意一个从库
- 兼顾了异步复制和同步复制的优点,即使出现主库宕机,至少还有一个从库有最新的数据,不存在数据丢失的风险