内容简介
1.Write-AheadLogging概览
2.Transactionlog
3.FPI
4.WAL文件与记录的内部结构
5.事务日志文件管理
6.实例恢复
7.归档
8.WAL写放大浅析
9.walminer、pg_waldump、wal2json工具浅析
Write-AheadLogging概览作用
故障中,保证数据不丢失
Point-in-TimeRecoveryPITR
StreamingReplicationSR
记录数据库所有的变更和行为
数据变更发生时:
先将变更后内容记入预写日志缓冲区
再将更新后的数据写入数据缓冲区
提交时:
预写日志缓冲区刷新到Disk
数据缓冲区写磁盘推迟
检查点发生时:
将所有数据缓冲区刷新到磁盘
Crash后的实例恢复PostgreSQL7.1之前的Crash
插入数据,页面未被刷新回磁盘,缓冲区中页面被弄脏。
继续插入数据,页面仍然未被刷新回磁盘。
OSORPGServerCrash后缓冲区中的数据丢失。
没有WAL的DBMS是极度不安全的。
PostgreSQL7.1之后的写操作
1.检查点进程周期性运行,启动时会向WAL文件写入一条记录,记录包含redopoint位置。(LSN位置)
2.插入1条数据,页面被加载到共享缓冲区,向该页面中插入一条元组,在LSN_1的位置插入一条WAL记录,在将表A的LSN从LSN_0变更为LSN_1。
3.当事务Commit时,WAL缓冲区会记录一条关于Commit行为的记录。再将WAL缓冲区中的XLOG记录写入到WAL段文件中。
4.插入第2条数据,向页面中插入新的元组,在LSN_2的位置插入一条新的WAL记录,在将表A的LSN从LSN_1变更为LSN2。
5.PGServerCrash时,尽管共享缓冲区中的所有数据将丢失,但是所有页面的修改,已经记录到了WAL段文件中。
概念
LogSequenceeNumberLSN日志序列号,标识了记录在事物日志中的位置,也代表WAL记录的唯一标识。
WAL写入时机,增删改时WAL记录写入WAL缓冲区,事物提交或终止时,被写入WAL段文件中。
重做点RedoPoint,最新的检查点开始时XLOG记录的写入位置(LSN)。
PostgreSQL实例恢复,是从哪一点开始恢复的?重做点RedoPoint。
src/include/storage/bufpage.h
pd_lsn-identifiesxlogrecordforlastchangetothispage.
标识对该页的最后更改的xlog记录。
PostgreSQL7.1之后的恢复
1.从重做点开始,依序读取正确的WAL段文件并重放XLOG记录。
2.从WAL段文件中读取第一条执行的insert的xlog记录,并将需要恢复的Page页面加载到共享缓冲区中。
3.重放xlog记录前,会比较xlog记录的LSN与相应页面的LSN。
a.如果XLOG记录的LSN比页面LSN大,XLOG记录中的数据部分就会被插入页面中,并将页面的LSN更新为XLOG记录的LSN。
b.如果XLOG记录的LSN比页面的LSN小,那么什么也不用做。
通过按照时间顺序重放写在WAL段文件中的XLOG记录来自我恢复。WAL可以理解成是一种重做日志,是用来做事物的前滚用的。
引入全页写后的Crash恢复块折断
full_page_writes作用:
是否开启全页写入,此参数是为了防止块折断(块损坏)的一种策略。
造成块折断的原因:
linux操作系统文件系统一个块一般是4k,而数据库则一般是一个块8k,当数据库的脏块刷新到磁盘上时,由于底层是两个块组成的,比如刷第一个操作系统块到磁盘上了,而当刷第二个操作系统块的时候发生了停电等突然停机事故,则就发生了块折断(数据块是否折断是根据块的checksum值来检查的)。
pg采用的机制:
当checkpoint后的一个块第一次变脏后就要整块写入到wal日志中,后续继续修改此块则只把修改的信息写入wal日志中,如果在此过程中发生了停电,则实例启动后会从checkpoint检查点,之后开始进行实例恢复,如果有块折断,则在全页写入的块为基础进行恢复,最后覆盖磁盘上的折断块,所以当每次checkpoint后如果数据有修改都会进行全页写入。
参数checkpoint_segments对checkpoint影响
参数checkpoint_segments控制checkpoint的间隔,如果checkpoint_segments设置太小就会造成频繁的checkpoint,进而导致写入了过多的全页,可能会造成wal日志的暴增.如果设置的过大,恢复时间会变长。
mysql为了防止块折断采用了doublewrite,oracle采用了redo+undo机制,其中undo记录了前镜像,而redo则既记录了修改数据又记录了undo块。
引入全页写(FPW)后的数据写入
概念
1.在写入脏页面的过程中,出现了宕机,导致页面损坏。WAL是无法在损坏的页面上重放的。
2.当一次检查点之后,页面第一次被修改时,页面+页面头部信息会作为XLOG日志写入到WAL段文件中。(整页镜像)
解析
检查点后,页面被第一次修改~~~
1.插入1条数据,页面被加载到共享缓冲区,向该页面中插入一条元组,在LSN_1的位置插入一条WAL记录(整页镜像),在将表A的LSN从LSN_0变更为LSN_1。
2.当事务Commit时,WAL缓冲区会记录一条关于Commit行为的记录。再将WAL缓冲区中的XLOG记录写入到WAL段文件中。
3.插入第2条数据,向页面中插入新的元组,在LSN_2的位置插入一条新的WAL记录,在将表A的LSN从LSN_1变更为LSN2。
引入全页写(FPW)后的Crash恢复
1.读取第1条记录,对应的xlog事务日志,加载对应的页面到共享缓冲区,按照整页写的规则,这条事物日志是一个全页镜像(备份区块)。
2.当一条XLOG日志是全页镜像(备份区块)时,和非全页镜像是有区别,XLOG记录的数据部分会直接覆盖当前页面。无视页面或XLOG记录中的LSN,然后将页面的LSN号更新为XLOG记录的LSN号。
3.第2条记录是非全页镜像,比对WAL的LSN和Page中的LSN号,将元组写入Page中。
检查点
检查点作用
1.将事务提交的修改写进disk(写脏数据);保证数据库的完整性和一致性。2.缩短恢复时间,将脏页写入相应的数据文件,确保修改后的文件通过fsync()写入到磁盘。
检查点触发条件
1.checkpoint_timeout设置的间隔时间自上一个检查点已经过去(默认间隔为秒(5分钟))。
2.在9.4或更早版本中,为checkpoint_segments设置的WAL段文件的数量自上一个检查点以来已经被消耗
(默认数量为3)。
3.在9.5或更高版本中,pg_xlog(在10或更高版本中为pg_wal)中的WAL段文件的总大小已超过参数
max_wal_size的值(默认值为1GB(64个文件))。
4.PostgreSQL服务器在smart或fast模式下停止。
5.当超级用户手动发出CHECKPOINT命令时,它的进程也会这样做。
6.写入WAL的数据量已达到参数max_wal_size(默认值:1GB)
7.执行pg_start_backup函数时
8.在进行数据库配置时(例如CREATEDATABASE/DROPDATABASE语句)
pg_crontrol文件
由于pg_control文件包含检查点的基本信息,因此它对于数据库恢复当然是必不可少的。
如果损坏或无法读取,则无法启动恢复过程,从而无法获得起点。
pg_control输出项说明
pg_controlversionnumber:是控制文件版本号。
Catalogversionnumber:是系统表版本号,格式是yyyymmddN。
Databasesystemidentifier:数据库系统号这个标识串是一个64bit的整数。
Databaseclusterstate:记录实例的状态。源码文件中看到数据库的几种状态:
startingup:表示数据库正在启动状态。
shutdown:数据库实例(非Standby)正常关闭后控制文件中就是此状态。
shutdowninrecovery:Standby实例正常关闭后控制文件中就是此状态。
shuttingdown:正常停库时,先做checkpoint,开始做checkpoint时,会把状态设置为此状态,
做完后把状态设置为shutdown。
incrashrecovery:数据库实例非异常停止后,重新启动后,会先进行实例的恢复,在实例恢复时的状态就是此状态。
inarchiverecovery:Standby实例正常启动后,就是此状态。
inproduction:数据库实例正常启动后就是此状态。Standby数据库正常启动后不是此状态
pg_controllastmodified:记录控制文件最后更新的时间。
Latestcheckpointlocation:数据库异常停止后再重新启动时,需要做实例恢复,实例恢复的过程是从WAL日志中,
找到最后一次的checkpoint点,最后一次的checkpoint点的信息记录在Latestcheckpoint项中。
Latestcheckpoint‘sREDOlocation:记录最近一次检查点时,Xlog的LSN号。
LatestcheckpointsREDOWALfile:记录WAL日志名,目录下pg_wal可以查到文件。
LatestcheckpointsTimeLineID:3当前时间线
LatestcheckpointsPrevTimeLineID:3
Latestcheckpointsfull_page_writes:on数据库参数全页写
LatestcheckpointsNextXID:0:
LatestcheckpointsNextOID:下一个OID(OID,object是pg内部使用,作为系统表的主键)
LatestcheckpointsNextMultiXactId:多事务ID
LatestcheckpointsNextMultiOffset:0多事务偏移量
LatestcheckpointsoldestXID:
LatestcheckpointsoldestXIDsDB:
LatestcheckpointsoldestActiveXID:
LatestcheckpointsoldestMultiXid:1旧多事务ID
LatestcheckpointsoldestMultisDB:
LatestcheckpointsoldestCommitTsXid:0最旧的事务号
LatestcheckpointsnewestCommitTsXid:0最新的事务号
Timeoflatestcheckpoint:Mon11Oct:46:24PMCST最后一次执行检查点时间
FakeLSNcounterforunloggedrels:0/3E8
Minimumrecoveryendinglocation:0/0这个值与Standby库应用WAL日志有关
Minrecoveryendinglocstimeline:0
Backupstartlocation:0/0记录了一个WAL日志的位置,用于主备库同步。
Backupendlocation:0/0记录了一个WAL日志的位置,用于主备库同步。
End-of-backuprecordrequired:no记录了备库恢复过程中的一些中间状态。
wal_levelsetting:replica
wal_level(枚举类型)pg10版本中,待选的值为minimal、replica、logical。
minimal--不能通过基础备份和wal日志恢复数据库
replica=9.6版本以前的archive和hot_standby--该级别支持wal归档和复制。
logical--在replica级别的基础上添加了支持逻辑解码所需的信息。在开启归档的系统中,进行...
wal_log_hintssetting:off
设置wal_log_hints这个参数使得能够记录特定提示位(hint-bit)的变化。
这个参数只能在服务器启动的时候被设置。默认值为off。
一些特定的工具会要求设置这个参数来正常的运行,所以将它设置为ON就好。
max_connectionssetting:最大连接数
max_worker_processessetting:8设置系统能够支持的后台进程的最大数量。
max_wal_senderssetting:10指定来自后备服务器或流式基础备份客户端的并发连接的最大数量(即同时运行WAL发送进程的最大数)。
src/include/access/xlog_internal.h
max_prepared_xactssetting:0
max_locks_per_xactsetting:64
track_