一、什么是double write(双写)
double write它针对的对象是脏数据,在将脏数据刷盘过程中产生。即一份脏数据写到共享表空间,一份写到真正的数据文件永久保存,也就是说写了两次的脏数据。所以称为double write。
二、什么是postgresql的full_page_writes
full_page_writes是控制是否开启全页写入,默认开启。作用就是为了防止块折断活动损坏的一种策略。
postgres=# show full_page_writes;
full_page_writes
------------------
on
(1 row)
三、为什么需要double write和full_page_writes
因为操作系统文件系统一个块大小一般是2k或者4k,而mysql数据页默认大小是16k,postgresql数据页大小默认是8k。所以,当时数据库脏数据刷新到磁盘的时候,由于底层是由4或2块组成,如果在刷第一个操作系统块到磁盘的时候,而在刷第二个操作系统块的时候发生停电的等故障,导致校验数据页或者块不完整,从而引起数据丢失。因此,通过解决这个问题mysql引入了double wirte,而postgresql使用full_page_writes。
四、double write的原理
共享表空间是ibdata文件中的划分出2M连续的空间,专门给double write刷脏页使用的。修改后的脏页先放到double write buffer区,等buffer空间满了,或者其他条件触发之后,再将double write buffer存的脏页写到共享表空间,之后再写入数据文件中。倘若,因为故障发生导致写入数据文件页数据不完整,则可以通过加载共享表空间中完整的页进行覆盖,数据页变得完整,再通过应用redo log进行恢复,数据就不会因此缺失。
1) 刷日志到磁盘的规则:
- 发出commit动作时,由innodb_flush_log_at_trx_commit控制
- 每秒刷一次。由innodb_flush_log_at_timeout值决定
- 当log buffer中已经使用的内存超过一半时
- 当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置
2) double write工作流程
五、full_page_writes的原理
当checkpoint后的一个块第一次变脏后就要整块写入到wal日志中,后续修改此块则只把修改的信息写入wal日志中,如果在此过程中发生停电等故障,则实例启动后会从checkpoint检查点之后,开始进行实例恢复,如果有块折断,则在全页写入的块为基础进行恢复,最后覆盖磁盘上得折断块,所以当每次check point后如果数据有修改都会进行全页写入。
postgres=# select name,setting from pg_settings where name like '%checkpoint%';
name | setting
------------------------------+---------
checkpoint_completion_target | 0.5
checkpoint_flush_after | 32
checkpoint_timeout | 300
checkpoint_warning | 30
log_checkpoints | off
(5 rows)
mysql double write参数文档:https://www.cnblogs.com/nandi001/p/11662992.html