点击上方蓝色文字关注我们哦

内容简介
1.Write-Ahead Logging概览
2.Transaction log
3.FPI
4.WAL文件与记录的内部结构
5.事务日志文件管理
6.实例恢复
7.归档
8.WAL写放大浅析
9.walminer、pg_waldump、wal2json工具浅析
Write-Ahead Logging概览作用
故障中,保证数据不丢失
Point-in-Time Recovery PITR
Streaming Replication SR
记录数据库所有的变更和行为
数据变更发生时:
先将变更后内容记入预写日志缓冲区
再将更新后的数据写入数据缓冲区
提交时:
预写日志缓冲区刷新到Disk
数据缓冲区写磁盘推迟
检查点发生时:
将所有数据缓冲区刷新到磁盘

Crash后的实例恢复
PostgreSQL 7.1之前的Crash

PostgreSQL 7.1之后的写操作

1.检查点进程周期性运行,启动时会向WAL文件写入一条记录,记录包含redo point位置。(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.PG Server Crash时,尽管共享缓冲区中的所有数据将丢失,但是所有页面的修改,已经记录到了WAL段文件中。
概念:
src/include/storage/bufpage.h

pd_lsn - identifies xlog record for last change to this page.标识对该页的最后更改的xlog记录。
PostgreSQL 7.1之后的恢复

引入全页写后的Crash恢复
1、块折断
full_page_writes作用:
造成块折断的原因:
pg采用的机制:
引入全页写(FPW)后的数据写入

概念
解析
引入全页写(FPW)后的Crash恢复

检查点
检查点作用
1.将事务提交的修改写进disk(写脏数据);保证数据库的完整性和一致性。
2.缩短恢复时间,将脏页写入相应的数据文件,确保修改后的文件通过fsync()写入到磁盘。
检查点触发条件
pg_crontrol文件

pg_control输出项说明pg_control version number: 是控制文件版本号。Catalog version number: 是系统表版本号,格式是yyyymmddN。Database system identifier: 数据库系统号 这个标识串是一个64bit的整数。Database cluster state: 记录实例的状态。源码文件中看到数据库的几种状态:starting up:表示数据库正在启动状态。shut down:数据库实例(非Standby)正常关闭后控制文件中就是此状态。shut down in recovery:Standby实例正常关闭后控制文件中就是此状态。shutting down:正常停库时,先做checkpoint,开始做checkpoint时,会把状态设置为此状态,做完后把状态设置为shut down。in crash recovery:数据库实例非异常停止后,重新启动后,会先进行实例的恢复,在实例恢复时的状态就是此状态。in archive recovery:Standby实例正常启动后,就是此状态。in production:数据库实例正常启动后就是此状态。Standby数据库正常启动后不是此状态pg_control last modified: 记录控制文件最后更新的时间。Latest checkpoint location: 数据库异常停止后再重新启动时,需要做实例恢复,实例恢复的过程是从WAL日志中,找到最后一次的checkpoint点,最后一次的checkpoint点的信息记录在Latest checkpoint项中。Latest checkpoint‘s REDO location: 记录最近一次检查点时,Xlog的LSN号。Latest checkpoint's REDO WAL file: 记录WAL日志名,目录下pg_wal可以查到文件。Latest checkpoint's TimeLineID: 3 当前时间线Latest checkpoint's PrevTimeLineID: 3Latest checkpoint ' s full_page_writes: on 数据库参数 全页写Latest checkpoint's NextXID: 0:1048576Latest checkpoint's NextOID: 22051 下一个OID(OID,object 是pg内部使用,作为系统表的主键)Latest checkpoint's NextMultiXactId: 65536 多事务IDLatest checkpoint's NextMultiOffset: 0 多事务偏移量Latest checkpoint's oldestXID: 480Latest checkpoint's oldestXID's DB: 13593Latest checkpoint's oldestActiveXID: 1048576Latest checkpoint's oldestMultiXid: 1 旧多事务IDLatest checkpoint's oldestMulti's DB: 16565Latest checkpoint's oldestCommitTsXid: 0 最旧的事务号Latest checkpoint's newestCommitTsXid: 0 最新的事务号Time of latest checkpoint: Mon 11 Oct 2021 01:46:24 PM CST 最后一次执行检查点时间Fake LSN counter for unlogged rels: 0/3E8Minimum recovery ending location: 0/0 这个值与Standby库应用WAL日志有关Min recovery ending loc's timeline: 0Backup start location: 0/0 记录了一个WAL日志的位置,用于主备库同步。Backup end location: 0/0 记录了一个WAL日志的位置,用于主备库同步。End-of-backup record required: no 记录了备库恢复过程中的一些中间状态。wal_level setting: replicawal_level (枚举类型) pg10版本中,待选的值为minimal、replica、logical。minimal --不能通过基础备份和wal日志恢复数据库replica = 9.6版本以前的archive和hot_standby --该级别支持wal归档和复制。logical --在replica级别的基础上添加了支持逻辑解码所需的信息。在开启归档的系统中,进行...wal_log_hints setting: off设置wal_log_hints这个参数使得能够记录特定提示位(hint-bit)的变化。这个参数只能在服务器启动的时候被设置。默认值为off。一些特定的工具会要求设置这个参数来正常的运行,所以将它设置为ON就好。max_connections setting: 600 最大连接数max_worker_processes setting: 8设置系统能够支持的后台进程的最大数量。max_wal_senders setting: 10指定来自后备服务器或流式基础备份客户端的并发连接的最大数量(即同时运行 WAL 发送进程 的最大数)。src/include/access/xlog_internal.hmax_prepared_xacts setting: 0max_locks_per_xact setting: 64track_commit_timestamp setting: off 记录事务提交时间。这个参数只能在postgresql.conf文件 或者服务器命令行上设置。缺省值是off。

Maximum data alignment: 8Database block size: 8192 数据块的大小Blocks per segment of large relation: 131072WAL block size: 16384 WAL日志块的大小Bytes per WAL segment: 16777216 WAL日志文件的大小Maximum length of identifiers: 64是指一些数据库对象名称的最大长度,如表名、索引名的最大长度,目前是64。Maximum columns in an index: 32表示一个索引最多多少列,目前为32个。Maximum size of a TOAST chunk: 1996是TOAST chunk的最大长度。TOAST是解决当列的内容太长,在一个数据块中存不下时的一种行外存储的方式。Size of a large-object chunk: 2048 大对象的chunk的大小Date/time type storage: 64-bit integers Date/time类型是用64bit的长整数表示。Float4 argument passing: by value Float4类型的参数是传值还是传引用。Float8 argument passing: by value Float8类型的参数是传值还是传引用。Data page checksum version: 1 数据块checksum的版本,默认为0,数据块没有使用checksum,1是启用。Mock authentication nonce: 8828beb6f158499535ed0f02f5788bdb104181b80f58e4c28ab6f4d87f849f5c
事务日志文件管理
WAL段文件
从PostgreSQL 11开始 initdb 时,可以通过 --wal-segsize选项配置wal段文件大小。00000001 00000000 00000001-------- -------- --------时间线 LogId LogSeg时间线:英文为timeline,是以1开始的递增数字,如1,2,3…LogId:32bit长的一个数字,是以0开始递增的数字,如0,1,2,3…LogSeg:32bit长的一个数字,是以0开始递增的数字,如0,1,2,3…
WAL段切换
WAL段管理

WAL 活动激增而需要更多文件


WAL文件与记录的内部结构



WAL记录写入

WAL Writer Process

恢复描述

src/bin/pg_controldata/pg_controldata.cstatic const char *dbState(DBState state){switch (state){case DB_STARTUP:return _("starting up");case DB_SHUTDOWNED:return _("shut down");case DB_SHUTDOWNED_IN_RECOVERY:return _("shut down in recovery");case DB_SHUTDOWNING:return _("shutting down");case DB_IN_CRASH_RECOVERY:return _("in crash recovery");case DB_IN_ARCHIVE_RECOVERY:return _("in archive recovery");case DB_IN_PRODUCTION:return _("in production");}return _("unrecognized status code");}


恢复举例 pd_lsn=Xlog的lsn

immediate模式关闭后的启动恢复

归档:
持续归档

归档配置
archive_mode = onarchive_command = 'DIR=/opt/arch/`date +%F`; test ! -d $DIR && mkdir -p $DIR; chmod 755 $DIR; test ! -f $DIR/%f && cp %p $DIR/%f; chmod 755 $DIR/%f'archive_command 中配置SCP命令可以把归档文件,拷贝到远端服务器进行备份。非主库清理归档配置archive_cleanup_command = 'pg_archivecleanup -d opt/peer_arch/`date +%F` %r 2>>cleanup.log‘本参数定义了在每个restart point时所执行的shell命令。archive_cleanup_command参数的目的是提供一个清理不再被standby server所需要的老的archived wal file的机制。restart point 是一个 point ,该point用于standby server重启recovery操作。
WAL写放大浅析——原因与影响
WAL写放大优化

优化WAL的副作用

pg_waldump、walminer、wal2json工具浅析
pg_waldump
pg_waldump显示WAL,将WAL以人可以读的格式输出,pg10+版本自带工具
pg_waldump decodes and displays PostgreSQL write-ahead logs for debugging.Options:-b, --bkp-details output detailed information about backup blocks-e, --end=RECPTR stop reading at WAL location RECPTR-f, --follow keep retrying after reaching end of WAL-n, --limit=N number of records to display-p, --path=PATH directory in which to find log segment files or adirectory with a ./pg_wal that contains such files(default: current directory, ./pg_wal, $PGDATA/pg_wal)-r, --rmgr=RMGR only show records generated by resource manager RMGR;use --rmgr=list to list valid resource manager names-s, --start=RECPTR start reading at WAL location RECPTR-t, --timeline=TLI timeline from which to read log records(default: 1 or the value used in STARTSEG)-V, --version output version information, then exit-x, --xid=XID only show records with transaction ID XID-z, --stats[=record] show statistics instead of records(optionally, show per-record statistics)select pg_switch_wal();create table test(id int);checkpoint;insert into test values(1);select pg_current_wal_insert_lsn();select pg_walfile_name('0/8011878');select file_name,upper(to_hex(file_offset)) file_offset from pg_walfile_name_offset('0/8011878');pg_waldump -p opt/pg_root/pg_wal -s 0/8011728 -e 0/8011878 000000010000000000000008
walminer
https://gitee.com/movead/XLogMinerPG源码编译 如果你从编译pg数据库开始将walminer目录放置到编译通过的PG工程的"../contrib/"目录下进入walminer目录执行命令make && make install创建walminer的extensioncreate extension walminer;添加要解析的wal日志文件-- 添加wal文件:select walminer_wal_add('/opt/pg_root/pg_wal');-- 注:参数可以为目录或者文件-- 移除wal文件:select walminer_wal_remove('/opt/test/wal');-- 注:参数可以为目录或者文件列出wal文件:select walminer_wal_list();select pg_switch_wal();checkpoint;select walminer_wal_add('/opt/pg_root/pg_wal');select walminer_wal_list();create table test(id int);insert into test(id) values(2);select walminer_all();select * from walminer_contents;
wal2json
https://github.com/eulerto/wal2json
tar -zxf wal2json-wal2json_2_4.tar.gzcd wal2json-wal2json_2_4export PATH=/home/euler/pg13/bin:$PATHmakemake installpostgresql.confwal_level = logicalmax_replication_slots = 10max_wal_senders = 10
终端A
$ pg_recvlogical -d postgres --slot test_slot --create-slot -P wal2json$ pg_recvlogical -d postgres --slot test_slot --start -o pretty-print=1 -o add-msg-prefixes=wal2json -f -
终端B
cd opt/psql -At -f example1.sql postgres
example1.sql
CREATE TABLE table1_with_pk (a SERIAL, b VARCHAR(30), c TIMESTAMP NOT NULL, PRIMARY KEY(a, c));CREATE TABLE table1_without_pk (a SERIAL, b NUMERIC(5,2), c TEXT);BEGIN;INSERT INTO table1_with_pk (b, c) VALUES('Backup and Restore', now());INSERT INTO table1_with_pk (b, c) VALUES('Tuning', now());INSERT INTO table1_with_pk (b, c) VALUES('Replication', now());SELECT pg_logical_emit_message(true, 'wal2json', 'this message will be delivered');SELECT pg_logical_emit_message(true, 'pgoutput', 'this message will be filtered');DELETE FROM table1_with_pk WHERE a < 3;SELECT pg_logical_emit_message(false, 'wal2json', 'this non-transactional message will be delivered even if you rollback the transaction');INSERT INTO table1_without_pk (b, c) VALUES(2.34, 'Tapir');-- it is not added to stream because there isn't a pk or a replica identityUPDATE table1_without_pk SET c = 'Anta' WHERE c = 'Tapir';COMMIT;DROP TABLE table1_with_pk;DROP TABLE table1_without_pk;
精彩回顾




【干货分享】MySQL用户权限及验证逻辑讲解
文章转载自云贝教育,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




