日志
undolog
undo log 两大作用:
-
实现事务回滚,保障事务的原子性。事务处理过程中,如果出现了错误或者用户执 行了 ROLLBACK 语句,MySQL 可以利用 undo log 中的历史数据将数据恢复到事务开始之前的状态。
-
实现 MVCC(多版本并发控制)关键因素之一。MVCC 是通过 ReadView + undo log 实现的。undo log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 select 语句)的时候,会根据事务的 Read View 里的信息,顺着 undo log 的版本链找到满足其可见性的记录。
undolog刷盘
undo log 和数据页的刷盘策略是一样的,都需要通过 redo log 保证持久化。
buffer pool 中有 undo 页,对 undo 页的修改也都会记录到 redo log。redo log 会每秒刷盘,提交事务时也会刷盘,数据页和 undo 页都是靠这个机制保证持久化的。
redolog
【在内存修改该 Undo 页面后,也需要记录对应的 redo log。】
【redolog文件是循环写的,因为只要刷盘脏页数据到磁盘,对应的redolog信息也没用了可以覆盖】
【事务的持久性就依赖于redolog日志】 重做日志缓冲区在logBuffer那里(在内存中)。----> 重做日志文件(在磁盘中),循环写(因为只要刷盘了,脏页就变成干净页,没有存在的意义了),不会永久保存,每隔一段时间清除用过的(因为用在异常时数据恢复,从而保证事务的持久性)。事务提交会把redologBuffer的数据页变更刷新到磁盘的redolog中】
WAL
为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,InnoDB 引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以 redo log 的形式记录下来(比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新),这个时候更新就算完成了。
后续,InnoDB 引擎会在适当的时候,由后台线程将缓存在 Buffer Pool 的脏页刷新到磁盘里,这就是 WAL (Write-Ahead Logging)技术。
WAL 技术指的是, MySQL 的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。
重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。 该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。
因为当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。
崩溃恢复
【undolog可以保证事务回滚,当事务commit崩溃,需要依靠redolog恢复事务】
有了 redo log,再通过 WAL 技术,InnoDB 就可以保证即使数据库发生异常重启,之前已提交的记录都不会丢失,这个能力称为 crash-safe(崩溃恢复)。可以看出来, redo log 保证了事务四大特性中的持久性。
redolog必要性
为什么需要 redo log 这个问题我们有两个答案:
刷盘
事务提交会把redologBuffer的数据页变更刷新到磁盘的redolog中】
个人理解: 事物每次提交的时候都会刷到磁盘redo log中,而不是直接将buffer pool中的数据直接刷到磁盘中(ibd文件中),是因为redo log 是顺序写,性能处理的够快,直接刷到ibd中,是随机写(随机IO性能低),性能慢。所以脏页是在下一次读的时候,或者后台线程采用一定的机制进行刷盘到ibd中。【WAL先写日志机制】 比如update的id跨度大,索引存储,所以随机写(很多数据,数据在磁盘中分散)很慢,要搞个顺序写(在磁盘一直往后写),写内存最快
注意:【redolog文件是循环写的,因为只要刷盘脏页数据到磁盘,对应的redolog信息也没用了可以覆盖】
-
redo log 文件满了,这时 MySQL 不能再执行新的更新操作,也就是说 MySQL 会被阻塞(因此所以针对并发量大的系统,适当设置 redo log 的文件大小非常重要),此时会停下来将 Buffer Pool 中的脏页刷新到磁盘中,然后标记 redo log 哪些记录可以被擦除,接着对旧的 redo log 记录进行擦除,等擦除完旧记录腾出了空间
【所以整个数据库删除不能用她来恢复,因为会缺少数据,只能用binlog】
缓存在 redo log buffer 里的 redo log 还是在内存中,它什么时候刷新到磁盘?
主要有下面几个时机:
-
MySQL 正常关闭时;
-
当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;
-
InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。
-
每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘。策略可由 innodb_flush_log_at_trx_commit 参数控制【内存结构的LogBuffer的参数】
-
当设置该参数为 0 时,表示每次事务提交时 ,还是将 redo log 留在 redo log buffer 中 ,该模式下在事务提交时不会主动触发写入磁盘的操作。
-
当设置该参数为 1 时,表示每次事务提交时,都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘,这样可以保证 MySQL 异常重启之后数据不会丢失。
-
当设置该参数为 2 时,表示每次事务提交时,都只是缓存在 redo log buffer 里的 redo log 写到 redo log 文件,注意写入到「 redo log 文件」并不意味着写入到了磁盘,因为操作系统的文件系统中有个 Page Cache(如果你想了解 Page Cache,可以看),Page Cache 是专门用来缓存文件数据的,所以写入「 redo log文件」意味着写入到了操作系统的文件缓存。
具体:
这三个参数的数据安全性和写入性能的比较如下:
-
数据安全性:参数 1 > 参数 2 > 参数 0
-
写入性能:参数 0 > 参数 2> 参数 1
binlog
【undo log 和 redo log 这两个日志都是 Innodb 存储引擎生成的。 binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用;】
binlog与redolog区别:
四个区别。
1、适用对象不同:
2、文件格式不同:
3、写入方式不同:
4、用途不同:
-
binlog 用于备份恢复、主从复制;
-
redo log 用于掉电等故障恢复。
主从复制
MySQL 集群的主从复制过程梳理成 3 个阶段:
-
写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。[Master 主库在事务提交时,会把数据变更记录在二进制文件Binlog中。]
-
同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。[从库(IOThread)读取数据库的二进制日志文件Binlog,写入到从库的中继日志Relay log。]
-
回放 Binlog:回放 binlog,并更新存储引擎中的数据。[slave(SQLThread)重做中继日志中的事件,将改变反映它自己的数据。]
注意:
主从复制模型:
刷盘
BufferPool
【提高数据库的读写性能】
InnoDB 会把存储的数据划分为若干个「页」,以页作为磁盘和内存交互的基本单位,一个页的默认大小为 16KB。因此,Buffer Pool 同样需要按「页」来划分。
Buffer Pool 中的页就叫做缓存页。此时这些缓存页都是空闲的,之后随着程序的运行,才会有磁盘上的页被缓存到 Buffer Pool 中。
注:感谢小林coding开源文档和黑马免费教程!!!!