数据库

首页 » 常识 » 问答 » PostgreSQL深度解析Write
TUhjnbcbe - 2024/12/23 16:46:00

内容简介

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_

1
查看完整版本: PostgreSQL深度解析Write