参考资料:
参考视频https://www.bilibili.com/video/BV1jA411A7qo?p=118
相关说明:
- 由上文可知,我们对数据进行操作时,需要将数据加载到缓存(buffer pool)中,交给lru链表管理,对于非唯一索引列的增删改,可以暂存在change buffer中,然后找机会和buffer pool中的数据合并
- 缓存中的数据在innoDB空闲时,持久化到磁盘中
- 但是这么做,当缓存中数据更改但是还没来得及持久化到磁盘中时,突然断电或者宕机,就会导致已变更的数据丢失。
- 所以,缓存中的数据每做一次更改,就记录该页的(B+树的)更改位置的新版本数据,并持久化到磁盘中,我们称之为redo log;又记录该页的(B+树的)更改位置的旧版本数据,并持久化到磁盘中,我们称之为undo log;redo log 可以用于当缓存中数据丢失的恢复,undo log用于事务回滚旧数据的恢复;
- 但是每更改一次就要进行一次IO操作,虽然由随机IO变成了顺序IO(解释①),但是仍然很浪费性能
- 所以就产生了log buffer,默认事务提交之前,对数据更改产生的日志(redo log和undo log)都存储在log buffer 中,事务提交时,才持久化到磁盘文件中,这样大大减少了IO操作
- log buffer的持久化策略如下,可以通过参数进行调节 innodb_flush_log_at_trx_commit 进行调节
- 0:每次事务提交时,根本不会去刷日志缓冲区。log buffer将每秒一次地写入到OS cache的log file中,并且log file的flush(刷到磁盘)上的Log Files操作同时进行。
- 1:每次事务提交时MySQL都会把log buffer的数据写入到OS cache的log file,并且flush(刷到磁盘)Log Files中去,该模式为系统默认。
- 2:每次事务提交时MySQL都会把log buffer的数据写入到OS cache的log file,但是flush(刷到磁盘)Log Files的操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。
相关解释:
- 解释①:
- 每更改一次缓存,就要持久化一次日志,这和每更改一次缓存,就将缓存持久化到磁盘中有什么不同?同样都是要进行IO操作。
-
这个和我们读取磁盘方式有关,电脑中的磁盘是一个不停旋转的圆盘,指针伴随着圆盘的旋转,由内而外不停的遍历,寻找地址,读取数据,当我们每更改一次缓存,就将缓存持久化到磁盘中时,系统就会根据指针的位置,随机的存储在磁盘中,当读取该数据时,就需要扫描全盘进行寻找,随机IO很浪费性能;但是,当我们每更改一次缓存,就变成日志信息存储在磁盘中时,由于磁盘中的文件是一片连续的IO,所以后台程序,在进行日志读取时,就不需要扫描全盘,同时也可以在后台将日志翻译成连续的数据空间,连续IO读取效率高。