MySQL-redo写入机制

以下内容来自mysql45讲第23讲mysql是怎么保证数据不丢的。

为了控制 redo log 的写入策略,InnoDB 提供了 innodb_flush_log_at_trx_commit 参数,它有三种可能取值:
设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中,不进行刷盘操作(系统默认master thread每隔1s进行一次重做日志的同步);
设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘;
设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache,不进行同步磁盘,由os自己决定什么时候同步到磁盘文件。

InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。
注意:事务执行中间过程的 redo log 也是直接写在 redo log buffer 中的,这些 redo log 也会被后台线程一起持久化到磁盘。
也就是说,一个没有提交的事务的 redo log,也是可能已经持久化到磁盘的。

实际上,除了后台线程每秒一次的轮询操作外,还有两种场景会让一个没有提交的事务的 redo log 写入到磁盘中:
一种是,redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动写盘。
注意,由于这个事务并没有提交,所以这个写盘动作只是 write,而没有调用 fsync,也就是只留在了文件系统的 page cache。
另一种是,并行的事务提交的时候,顺带将这个事务的 redo log buffer 持久化到磁盘。
假设一个事务 A 执行到一半,已经写了一些 redo log 到 buffer 中,这时候有另外一个线程的事务 B 提交,如果 innodb_flush_log_at_trx_commit 设置的是 1,那么按照这个参数的逻辑,事务 B 要把 redo log buffer 里的日志全部持久化到磁盘。这时候,就会带上事务 A 在 redo log buffer 里的日志一起持久化到磁盘(也就是redo的组提交)

WAL机制主要得益于两个方面: redo log 和 binlog 都是顺序写,磁盘的顺序写比随机写速度要快;
组提交机制:可以大幅度降低磁盘的 IOPS 消耗。

redolog_buffer写入redolog_file的单位是512字节,而磁盘IO的最小单位也是512字节,所以无所谓数据损坏(相比double_write)
MySQL的数据页默认是16K,而文件系统的数据页(块)大小是4K,所以刷脏时有可能会出现坏页现象,所以才出现了double_write

posted @   Enzo_Ocean  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示