write ahead log预写日志,简称WAL日志。WAl日志是数据库中的重要组成部分,相当于oracle数据库中的redo log,该日志存储在data目录下的sys_wal目录中。
当数据库发生数据更新时:
a)changing:先将数据的更新写入到wal的buffer中,然后再将数据更新写入data buffer;
b)commit:先将wal的buffer刷到磁盘,然后给客户端返回commit,此时更新的数据本身有可能还在data buffer中;
c)checkpoint:checkpoint进程会将data buffer中的脏页刷到磁盘上。
触发checkpoint的情况有哪些?
a)手动执行CHECKPOINT;
b)执行需要检查点的命令:sys_start_backup、sys_ctl stop | restart 等;
c)达到检查点的配置时间:checkpoint_timeout;
d)max_wal_size已满。
其中第一和第二点与数据库的配置无关,接下里我们主要关注后面两点:
首先,checkpoint_timeout是两个检查点之间的最大间隔时间。默认是5min,如果增加该时间会增加数据库崩溃恢复所需的时间,因为检查点后的所有wal记录,在崩溃恢复的时候需要重新解析做数据回放,检查点越密集,对应需要处理的记录越少,恢复越快(但是频繁的设置检查点会增加数据库的负担,影响数据库性能,需要综合考虑)。可以使用show checkpoint_timeout;这个sql语句来查看设置的检查点时间。
其次,max_wal_size是在最大检查点间隔时间内允许写入的WAL日志上线,如果达到该参数设置的阈值,将自动触发checkpoint操作。但是这是一个软限制,在特殊的情况下有可能会超过设定的阈值(如数据库重度负载的情况下可能不会触发checkpoint)。可以使用show max_wal_size;这个sql语句来查看设置的wal限制阈值。
额外说明:
与max_wal_size类似的还有一个参数min_wal_size,因为WAL是循环顺序写入的,于是会重复使用给定的内存空间,当剩余的空间大小大于min_wal_size的时候,先前写过的日志记录并不会被删除(最新检查点前的一些日志记录),直到小于该参数的设定值时,才会将那些旧的WAL删除,以供后续的WAL日志循环写入。
WAL切换的步骤如下:
单个WAL日志写满的时候(默认16M,编译数据库的时候指定)继续写下一个WAL日志,直到磁盘空间不足min_wal_size的时候才会将旧的WAL文件回收以便循环使用。但是这种模式有一个弊端就是如果checkpoint前产生了大量的WAl日志,就会导致发生checkpoint的时候对数据库性能影响巨大,因此又引入了一个参数checkpoint_completion_target来进行调整。
Checkpoint_completion_target:指定检查点的完成目标,作为检查点之间总时间的一部分。默认设置为0.5。假设checkpoint_timeout的时间设置为30min,而在此期间WAL日志生成了10G,那么设置为0.5就允许在15min内完成checkpoint,调大这个值就可以降低checkpoint对数据库性能的影响,但是当数据库崩溃的时候,恢复的时间将会增加。
总结:
a)大多数的检查点应该是基于时间的,即由checkpoint_timeout来触发;
b)性能与数据库恢复时间之间应该做好抉择;
c)设置checkpoint_timeout后,通过估计WAL的数据量选择max_wal_size参数的值;
d)设置checkpoint_completion_target以便内核将数据刷到磁盘的时间足够(但不是太多)。 更多信息,参见https://help.kingbase.com.cn/v8/index.html