1.什么是全页写
修改一个块的时候,把块读到内存中,commit后,WAL写进程会触发写,把修改的块写到WAL日志文件,如果再往这个块中插入一条数据,数据缓冲区里面的块有两条数据了,再次commit后,PG会把这个事务写到事务缓冲区,再把事务缓冲区的事务写到WAL 文件中。
第一个commit就是全页写
所以全页写的概念就是:把数据块写到WAL日志中。
目的:解决块不一致问题,保护数据的完整性。
缺点:会导致WAL日志膨胀,增加额外的I/O
控制参数:
2.全页写的模式
1.非强制模式:
最近一次检查点之后,第一次修改的数据块会进行全页写,后续再修改时不会进行全页写,知道下一次检查点法师。
2.强制模式:
进行备份的时候,会自动执行强制模式,在备份期间修改的数据块会全部写入WAL当中。
当执行pg_start_backup函数时,系统也会进入全页写模式,执行pg_stop_backup 时,退出全页写模式。
3.什么是块不一致?
1.操作系统进行I/O操作时,总是以块为单位,比如512字节,1kb,4kb(xfs)。
2.数据块进行I/O操作也是以块为单位,数据库块一般是操作系统块的整数倍,Oracle buffer cache就可以指定不同的块大小。
3.当数据库写一个数据块的时候,比如说操作系统的块是1k,数据库的块是8k,那么这个时候就要写8次,进行8次I/O,如果在I/O过程中系统断电,这个时候就导致了块不一致。
就比如这8次I/O 如果进行了4次I/O,这时候断电了,就导致了 要写进磁盘的这8块,前四次是新的,后四次由于断电导致了没有写入,是旧的,就导致了块不一致。
4.PG如何解决的?
其实刚开始也讲了,因为bgwr 进程写进程触发需要一定的条件,具有时间间隔,所以为了预防块不一致,就先把修改过数据的整个块放进WAL日志中,这和MySQL的两次写其实很像,MySQL 为了预防块不一致,会先把buffer pool 里面修改的块完全copy到内存的另外一个区域-doublewrite buffer,之后从两次写缓冲区中分两次 ,第一次写入磁盘共享表空间中(顺序写,速度很快)。第二次再将doublewrite buffer中的脏页数据写入实际的各个表空间文件(离散写);
5.全页写是否关闭?
1.如果数据库有完整的备份,可以禁用全页写。
2.如果优先考虑数据库整体性能,可以禁用全页写。
3.选择能够组织部分页面写入的文件系统(ZFS)。