学习链接
https://www.bilibili.com/video/BV1xh411Z79d?p=38
https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html
日志模块简介
Bin log:逻辑日志(记录逻辑运算过程),相当于AOF,也相当于git的log记录所有操作
Redo log:物理日志(记录最终逻辑运算结果),相当于RDB
二进制日志是在存储引擎的上层产生的,不管是什么存储引擎,对数据库进行了修改都会产生二进制日志。而redo log是innodb层产生的,只记录该存储引擎中表的修改。并且二进制日志先于redo log被记录。
RedoLog事务日志记录的是物理页的情况,它具有幂等性,因此记录日志的方式极其简练。幂等性的意思是多次操作前后状态是一样的,例如新插入一行后又删除该行,前后状态没有变化。而二进制日志记录的是所有影响数据的操作,记录的内容较多。例如插入一行记录一次,删除该行又记录一次。
redolog也有重写机制将最新结果写入到log中,注意与AOF的重写不一样,AOF是合并操作,redolog是重写数据
Bin log
二进制日志:MYSQL提供了工具去解析二进制日志,解析出标志位等
物理日志会有大小限制,而bin log则没有大小限制
Flush logs操作后,之后的操作生成到新的bin log日志文件中
Bin log写入:
事务执行过程中先把日志写到binlog cache中,等事务提交的时候再把cache写到binlog文件fsync落盘并清空cache,这一点和redolog/AOF很像。一个事务的 binlog不能被拆开,不论事务多大也要确保一次性写入binlog。每个线程都会申请一块binlog cache,内存空间大小由参数 binlog_cache_size控制。如果超过参数设置的大小就要暂存到磁盘。而write和fsync 的时机由参数sync_binlog决定(双1参数之1)
查看bin log日志
End_log_pos标志位,标志操作在数据库的起始位置
timestamp:时间点记录
恢复可以恢复按照时间段进行恢复,也可以按照pos位置进行恢复,恢复数据库中某一段位置区间内所有的数据
记录了数据库与表名
恢复数据的操作:
Redo Log
背后是WAL机制:ignite持久化机制,先写日志再写磁盘
先写日志,再写磁盘
检查机制:检测到MySQL在空闲时将redo log file中的数据写入到磁盘文件中,防止数据库雪崩
内存中(buffer pool)未刷到磁盘的数据称为脏数据(dirty data)。由于数据和日志都以页的形式存在,所以脏页表示脏数据和脏日志。
不仅仅是日志需要刷盘,脏数据页也一样需要刷盘。
https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html
在innodb中,数据刷盘的规则只有一个:checkpoint。
checkpoint触发后,会将buffer中脏数据页和脏日志页都刷到磁盘。
innodb存储引擎中checkpoint刷入机制上来说分为如下两种:
sharp checkpoint:在重用redo log文件(例如切换日志文件)的时候,将所有已记录到redo log中对应的脏数据刷到磁盘。
fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:
- master thread checkpoint:由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。
- flush_lru_list checkpoint:从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。
- async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
- dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。
- 对于每次commit操作的设置
由于刷脏页需要一定的时间来完成,所以记录检查点的位置是在每次刷盘结束之后才在redo log中标记的。
关闭时的刷新:
MySQL停止时是否将脏数据和脏日志刷入磁盘,由变量innodb_fast_shutdown={ 0|1|2 }控制,默认值为1,即停止时只做一部分purge,忽略大多数flush操作(但至少会刷日志),在下次启动的时候再flush剩余的内容,实现fast shutdown。
日志位置:
写入流程:
可以设置几个组可以设置组里面有几个文件
类似于Java GC的操作原理
再次切换到文件1,检测其中哪些已经写入到数据库,然后擦除这部分日志中的记录,之后再开始写入
如果两个文件都已经写满,那么就会进行一次Major GC,将两个文件的数据同步到数据库中然后再向后执行
checkpoint就是去检查文件是否有空闲位置
在major GC执行时会停下数据库,不让数据继续进行提交,现将文件中的数据同步到数据库中,将文件擦除一部分然后再接受新的任务
日志与内存页刷盘
刷日志到磁盘有以下几种规则:
1.发出commit动作时。已经说明过,commit发出后是否刷日志由变量 innodb_flush_log_at_trx_commit 控制。
2.刷新时间设置:每秒刷一次。这个刷日志的频率由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。要注意,这个刷日志频率和commit动作无关。
3.当log buffer中已经使用的内存超过一半时。
4.当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置。
被动刷脏页的时机:
Redo Log写满了, 需要将 checkpoint 向前推进, 以便继续写入日志
checkpoint 向前推进时, 需要将推进区间涉及的所有脏页刷新到磁盘.
内存不足, 需要淘汰一些内存页(最久未使用的)给别的数据页使用.
此时如果是干净页, 则直接拿来复用.
如果是脏页, 则需要先刷新到磁盘(直接写入磁盘, 不用管Redo Log, 后续Redo Log刷脏页时会判断对应数据页是否已刷新到磁盘), 使之成为干净页再拿来使用。
数据库系统空闲时
当然平时忙的时候也会尽量刷脏页.
数据库正常关闭
此时需要将所有脏页刷新到磁盘.
InnoDB需要控制脏页比例来避免Redo Log写满以及单次淘汰过多脏页过多的情况.
怎么将提交性能提升到最好
0、1、2的不同设置:都是1s,看怎么写
0:间隔1s将log buffer中的内容写入到OS buffer中,因为要操作底层磁盘,需要在内核空间中进行
问题:提交过程中宕机,还未写入到OS Buffer中,就会造成数据丢失,同AOF的写文件模式
1:安全性最高,性能比较差(默认)
2:数据也可能丢失
值为2和0的时候,它们的差距并不太大,但2却比0要安全的多:因为0在当前服务挂了(MySQL挂了)即不可用,而2只有在操作系统挂了之后才会丢失数据。它们都是每秒从os buffer刷到磁盘,它们之间的时间差体现在log buffer刷到os buffer上。因为将log buffer中的日志刷新到os buffer只是内存数据的转移,并没有太大的开销,所以每次提交和每秒刷入差距并不大。
更好的插入数据的做法是将值设置为1,然后修改存储过程,将每次循环都提交修改为只提交一次,这样既能保证数据的一致性,也能提升性能
还有刷盘时间的设置,设置刷新频率
WAL机制:
https://segmentfault.com/a/1190000020835301