暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL中控制文件的解析与恢复

数据库杂记 2023-02-21
492
最近遇到有人问起PG中控制文件的一些使用问题,总结了一下。

1、PG控制文件简介

1.1、存储的位置

它的路径位于:$PGDATA/global/pg_control

相关信息,可以用命令pg_controldata得到:

    [10:41:27-postgres@centos2:/var/lib/pgsql/14/data/global]$ pg_controldata -D $PGDATA
    pg_control version number: 1300
    Catalog version number: 202107181
    Database system identifier: 7138432685960386315
    Database cluster state: in production
    pg_control last modified: Sun 11 Dec 2022 11:19:22 AM CST
    Latest checkpoint location: 1/2A000180
    Latest checkpoint's REDO location: 1/2A000148
    Latest checkpoint's REDO WAL file: 00000001000000010000002A
    Latest checkpoint's TimeLineID: 1
    Latest checkpoint's PrevTimeLineID: 1
    Latest checkpoint's full_page_writes: on
    Latest checkpoint's NextXID: 0:1461
    Latest checkpoint's NextOID: 31466
    Latest checkpoint's NextMultiXactId: 1
    Latest checkpoint's NextMultiOffset: 0
    Latest checkpoint's oldestXID: 727
    Latest checkpoint's oldestXID's DB: 1
    Latest checkpoint's oldestActiveXID: 1461
    Latest checkpoint's oldestMultiXid: 1
    Latest checkpoint's oldestMulti's DB: 1
    Latest checkpoint's oldestCommitTsXid:0
    Latest checkpoint's newestCommitTsXid:0
    Time of latest checkpoint: Sun 11 Dec 2022 11:19:22 AM CST
    Fake LSN counter for unlogged rels: 0/3E8
    Minimum recovery ending location: 0/0
    Min recovery ending loc's timeline: 0
    Backup start location: 0/0
    Backup end location: 0/0
    End-of-backup record required: no
    wal_level setting: replica
    wal_log_hints setting: off
    max_connections setting: 100
    max_worker_processes setting: 8
    max_wal_senders setting: 10
    max_prepared_xacts setting: 0
    max_locks_per_xact setting: 64
    track_commit_timestamp setting: off
    Maximum data alignment: 8
    Database block size: 8192
    Blocks per segment of large relation: 131072
    WAL block size: 8192
    Bytes per WAL segment: 16777216
    Maximum length of identifiers: 64
    Maximum columns in an index: 32
    Maximum size of a TOAST chunk: 1996
    Size of a large-object chunk: 2048
    Date/time type storage: 64-bit integers
    Float8 argument passing: by value
    Data page checksum version: 0
    Mock authentication nonce: aaa8abf569631ec60ba05e3f625495da70007738b831e46e1cfda0d26c370987

    1.2、什么是控制文件

    控制文件里存储了数据库唯一系统标识符、系统状态数据、数据库启动前系统必须恢复到的检查点信息、数据库的配置兼容backend进程执行的参数、指明类型timestamp、interval、time内部格式的标志、指明不同类型传值(pass-by-value)状态的标志以及一些数据库的重要信息。

    我们可以通过pg_controldata命令直接读取PostgreSQL控制文件内容。

    控制文件内容主要分为是三部分,初始化静态信息、WAL及检查点的动态信息、一些数据库配置信息。

    控制文件物理路径$PGDATA/global/pg_control,源码路径src/include/catalog/pg_control.h。

    2、控制文件解析

    通过pg_controldata命令查看控制文件内容,我们按照初始化静态信息、WAL及检查点的动态信息、一些数据库配置信息三部分进行解析。

    2.1、初始静态信息解析

      [10:41:27-postgres@centos2:/var/lib/pgsql/14/data/global]$ pg_controldata -D $PGDATA
      pg_control version number: 1300
      Catalog version number: 202107181
      Database system identifier: 7138432685960386315
      Database cluster state: in production
      pg_control last modified:             Sun 11 Dec 2022 11:19:22 AM CST

      我们找一下pg_control.h中的信息:(pg14的codeline)

        source path: 
        C:\tools\pgsql\14.4\include\server\catalog\pg_control.h
        C:\SAPDevelop\3rdpart\postgres\postgres\src\include\catalog\pg_control.h


        /* Version identifier for this pg_control format */
        #define PG_CONTROL_VERSION 1300

        pg_control version number: 1300 是控制文件版本号。

          source path:
          C:\SAPDevelop\3rdpart\postgres\postgres\src\include\catalog\catversion.h


          #ifndef CATVERSION_H
          #define CATVERSION_H


          /*
          * We could use anything we wanted for version numbers, but I recommend
          * following the "YYYYMMDDN" style often used for DNS zone serial numbers.
          * YYYYMMDD are the date of the change, and N is the number of the change
          * on that day. (Hopefully we'll never commit ten independent sets of
          * catalog changes on the same day...)
          */


          /* yyyymmddN */
          #define CATALOG_VERSION_NO 202107181

          Catalog version number: 202107181。是系统表版本号,格式是yyyymmddN。记录系统不兼容性的改变。**N是yyymmdd当天改变的次数。**具体可以查看源码文件src/include/catalog/catversion.h。

          Database system identifier: 7138432685960386315 数据库系统号,这个标识串是一个64bit的整数,其中包含了创建数据库的时间戳和initdb时初始化的进程号,具体初始化方法可查看源码文件src/backend/access/transam/xlog.c。创建时间可以通过to_timestamp转换查看到(这个时间就是数据库安装的时间)。

          Database cluster state: in production 记录实例的状态。源码文件中看到数据库的几种状态,源码在pg_control.h中:

            /*
            * System status indicator. Note this is stored in pg_control; if you change
            * it, you must bump PG_CONTROL_VERSION
            */
            typedef enum DBState
            {
            DB_STARTUP = 0,
            DB_SHUTDOWNED,
            DB_SHUTDOWNED_IN_RECOVERY,
            DB_SHUTDOWNING,
            DB_IN_CRASH_RECOVERY,
            DB_IN_ARCHIVE_RECOVERY,
            DB_IN_PRODUCTION
            } DBState;

            含义如下:

            • 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数据库正常启动后in archive recovery状态。

            pg_control last modified: Sun 11 Dec 2022 11:19:22 AM CST  记录控制文件上次更新的时间

            2.2、WAL及检查点的动态信息

              Latest checkpoint location:           1/2A000180  最后一次检查点
              Latest checkpoint's REDO location: 1/2A000148 记录数据库日志文件上检查点,数据库异常关闭后会从这个点开始恢复。当数据库刚启动时Latest checkpoint location与Latest checkpoint's REDO location一致,随着时间的变化Latest checkpoint's REDO location会随之变化。
              Latest checkpoint's REDO WAL file: 00000001000000010000002A
              Latest checkpoint's TimeLineID: 1 当前时间线
              Latest checkpoint's PrevTimeLineID: 1 前一个时间线,如果这个记录开始一个新的时间线(否则等于 ThisTimeLineID)
              Latest checkpoint's full_page_writes: on 数据库参数,默认值为on,详见官方文档第十九章服务器配置。
              Latest checkpoint's NextXID: 0:1461 /下一个空闲XID,前面是新纪元值,冒号后面是下一个事务ID,当前事务号最大值安全值可以在pg_xact目录下通过文件名计算出来安全值。
              Latest checkpoint's NextOID: 31466 //下一个空闲OID(OID,object 是pg内部使用,作为系统表的主键)
              Latest checkpoint's NextMultiXactId: 1 //下一个空闲的MultiXactId,多事务ID,可以通过pg_multixact/offsets文件名计算出来安全值。
              Latest checkpoint's NextMultiOffset: 0 //下一个空闲的 MultiXact 偏移,多事务偏移量,通pg_multixact/members文件夹下计算出此参数的安全值。
              Latest checkpoint's oldestXID: 727 //集群范围的最小 datfrozenxid ,WAL中存储的是oldest XID之后的XID,也就是说这个XID之后的事务,都保留了事务提交的状态值,之前的WAL可能被删除或者正在被删除。
              Latest checkpoint's oldestXID's DB: 1 // 具有最小datfrozenxid 的数据库,可以通过pg_database表进行查看。
              Latest checkpoint's oldestActiveXID: 1461 //最旧的的仍在运行的事务ID
              Latest checkpoint's oldestMultiXid: 1
              Latest checkpoint's oldestMulti's DB: 1
              Latest checkpoint's oldestCommitTsXid:0 // 有效提交的最旧 Xid 时间戳
              Latest checkpoint's newestCommitTsXid:0 // 有效提交的最新 Xid*时间戳
              Time of latest checkpoint: Sun 11 Dec 2022 11:19:22 AM CST // 最后一次执行检查点时间
              Fake LSN counter for unlogged rels: 0/3E8 // 当前假 LSN 值,用于未记录的 rels
              Minimum recovery ending location: 0/0 // standby节点最小恢复结束位置
              Min recovery ending loc's timeline: 0 // standby节点最小恢复结束时间线
              Backup start location: 0/0 // 备库开始同步主库时重做日志的位置。
              Backup end location: 0/0 //备库同步结束后重做日志的位置。
              End-of-backup record required: no //记录了备库恢复过程中的一些中间状态(yes正在恢复/no未恢复)

              关于:Latest checkpoint location: 1/2A000180 与 Latest checkpoint's REDO location: 1/2A000148

                [11:23:08-postgres@centos2:/pgccc/pgdata/pg_wal]$ pg_waldump 00000001000000010000002A | grep 2A000148
                pg_waldump: fatal: error in WAL record at 1/2A0001F8: invalid record length at 1/2A000230: wanted 24, got 0
                rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 1/2A000148, prev 1/2A000110, desc: RUNNING_XACTS nextXid 1461 latestCompletedXid 1460 oldestRunningXid 1461
                rmgr: XLOG len (rec/tot): 114/ 114, tx: 0, lsn: 1/2A000180, prev 1/2A000148, desc: CHECKPOINT_ONLINE redo 1/2A000148; tli 1; prev tli 1; fpw true; xid 0:1461; oid 31466; multi 1; offset 0; oldest xid 727 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 1461; online

                看看上边的内容:lsn: 1/2A000180, prev 1/2A000148

                Latest checkpoint's REDO WAL file: 00000001000000010000002A 记录WAL日志名,目录下pg_wal可以查到文件。

                下图是一个备节点的控制文件关于standby的信息,这两个值决定了我们必须恢复到的最低点:

                关于Backup end location:


                2.3、一些配置信息:

                下边是一些配置信息,相关内容可以从官方文档里头得到。

                  wal_level setting:                    replica
                  wal_log_hints setting: off
                  max_connections setting: 100
                  max_worker_processes setting: 8
                  max_wal_senders setting: 10
                  max_prepared_xacts setting: 0
                  max_locks_per_xact setting: 64
                  track_commit_timestamp setting: off

                  再看后边的一些内容:

                    Maximum data alignment:               8 		//8 元组的对齐要求,数据结构最大的对齐值
                    Database block size: 8192 //数据块的大小,参数block_size
                    Blocks per segment of large relation: 131072 //每段大关系的块,参数segment_size
                    WAL block size: 8192 //文件中的块大小,参数wal_block_size
                    Bytes per WAL segment: 16777216 //每个WAL 段的大小,数据库初始化时通过--wal-segsize参数进行修改
                    Maximum length of identifiers: 64 //目录名称字段宽度,是指一些数据库对象名称的最大长度,如表名、索引名的最大长度,目前是64,src/include/pg_config_manual.h中的NAMEDATALEN
                    Maximum columns in an index: 32 //表示一个索引最多多少列,目前为32个, 参考:src/include/pg_config_manual.h中的INDEX_MAX_KEYS。src/include/pg_config_manual.h记录PostgreSQL一些限制信息。Maximum length of identifiers和Maximum columns in an index可以通过修改源码文件重新编译进行重置。
                    Maximum size of a TOAST chunk: 1996 //TOAST 表中的块大小,是TOAST chunk的最大长度。TOAST是解决当列的内容太长,在一个数据块中存不下时的一种行外存储的方式,这个值的计算方式详见src/include/access/tuptoaster.h。
                    Size of a large-object chunk: 2048 //大对象的块的大小,这个值的计算方式详见utils/snapshot.h
                    Date/time type storage: 64-bit integers //Date/time表示类型
                    Float8 argument passing: by value //参数传递方式,按值传递
                    Data page checksum version: 0 //数据页是否受校验和保护?如果没有校验和版本则为零,数据块checksum的版本,默认为0,数据块没有使用checksum,1是启用。运行initdb时加了-k参数,PG才会在数据块上启用checksum功能。
                    Mock authentication nonce: aaa8abf569631ec60ba05e3f625495da70007738b831e46e1cfda0d26c370987 //用于需要进行的认证请求基于集群唯一的值

                    3、重建控制文件在实践中的应用

                    重建控制文件在pg9.6前使用 pg_resetxlog,pg10之后使用pg_resetwal清理wal日志或重置控制文件中一些控制信息。配置指导详见源码doc/src/sgml/html/app-pgresetwal.html

                    下面看下命令各个参数具体含义:

                      [11:20:09-postgres@centos2:/var/lib/pgsql/14/data/global]$ pg_resetwal --help
                      pg_resetwal resets the PostgreSQL write-ahead log.
                      Usage:
                      pg_resetwal [OPTION]... DATADIR


                      Options:
                      -c, --commit-timestamp-ids=XID,XID
                      set oldest and newest transactions bearing
                      commit timestamp (zero means no change)
                      [-D, --pgdata=]DATADIR data directory
                      -e, --epoch=XIDEPOCH set next transaction ID epoch
                      -f, --force force update to be done
                      -l, --next-wal-file=WALFILE set minimum starting location for new WAL
                      -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID
                      -n, --dry-run no update, just show what would be done
                      -o, --next-oid=OID set next OID
                      -O, --multixact-offset=OFFSET set next multitransaction offset
                      -u, --oldest-transaction-id=XID set oldest transaction ID
                      -V, --version output version information, then exit
                      -x, --next-transaction-id=XID set next transaction ID
                      --wal-segsize=SIZE size of WAL segments, in megabytes
                      -?, --help show this help, then exit
                      • -f, --force          force update to be done

                      即使pg_resetwal无法从pg_control中确定有效的数据(也可以说成此时控制文件损坏或者缺失),也强迫pg_resetwal继续运行。

                      • -n, --dry-run         no update, just show what would be done

                      pg_resetwal打印从pg_control重构出来的值以及要被改变的值,然后不修改任何东西退出。这主要是一个调试工具,但是可以用来在允许pg_resetwal真正执行下去之前进行完整性检查。

                      • -V, --version         output version information, then exit

                      显示版本信息然后退出。

                      • -?, --help           show this help, then exit

                      只有当pg_resetwal无法通过读取pg_control确定合适的值时,才需要下列选项。安全值可以按下文所述来确定。对于接收数字参数的值,可以使用前缀0x指定16进制值。

                      • -c, --commit-timestamp-ids=XID,XID  set oldest and newest transactions bearing

                      手工设置提交时间可以检索到的最老的和最新的事务ID。

                      能检索到提交时间的最老事务 ID 的安全值(第一部分)可以通过在数据目录下pg_commit_ts目录中数字上最小的文件名来决定。反过来,能检索到提交时间的最新事务 ID 的安全值(第二部分)可以通过同一个目录中数字上最大的文件名来决定。文件名都是十六进制的。对应控制文件中,查看pg_commit_ts目录,一般情况下该目录均为空,需要开启track_commit_timestamp参数才会记录事物提交时间,在未开启的情况下:

                      Latest checkpoint's oldestCommitTsXid:0

                      Latest checkpoint's newestCommitTsXid:0

                      • [-D, --pgdata=]DATADIR     data directory

                      数据库目录。

                      • -e, --epoch=XIDEPOCH      set next transaction ID epoch

                      手工设置下一个事务 ID 的 epoch。事务 ID 的 epoch 实际上并没有存储在数据库中的任何地方,除了被pg_resetwal设置在这个域中,所以只要关心的是数据库本身,任何值都可以用,可以不用设置。

                      • -l, --next-wal-file=WALFILE  set minimum starting location for new WAL

                      参数通过指定下一个WAL段文件的名称,手动设置WAL启动位置该选项使用WAL文件名,而不是LSN。下一个段的名字应该大于当前存在pg_wal目录下的任何WAL段文件名。

                      通过指定下一个WAL段文件名称来手工设置WAL开始位置。下一个WAL段文件的名称应该比当前存在于数据目录下pg_wal目录中的任意 WAL 段文件名更大。这些名称也是十六进制的并且有三个部分。第一部分是“时间线 ID”并且通常应该被保持相同。例如,如果00000001000000320000004A是pg_wal中最大的项,则使用-l 00000001000000320000004B或更高的值。

                      注意在使用非默认WAL段尺寸时,WAL文件名中的数字与系统函数和系统视图报告的LSN不同。这个选项要的是WAL文件名而不是LSN。

                      注意pg_resetwal本身查看pg_wal中的文件并选择一个超出最新现存文件名的默认-l设置。因此,只有当你知道 WAL 段文件当前不在pg_wal中时,或者当pg_wal的内容完全丢失时,才需要对-l的手工调整,例如一个离线归档中的项。

                      这些名称也是十六进制的,文件名包含三部分 ,第一部分时间线号(timeline ID) ,第二部分逻辑日志号 ,第三部分日志段号。

                      000000030000000A000000CA

                      • -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID

                      手工设置下一个多事物ID和最老的多事务ID。确定下一个多事务 ID(第一部分)的安全值的方法:在数据目录下的pg_multixact/offsets目录中查找最大的数字文件名,然后在它的基础上加一并且乘以 65536(0x10000)。反过来,确定最老的多事务 ID(-m的第二部分)的方法:在同一个目录中查找最小的数字文件名并且乘以 65536。文件名是十六进制的数字,因此实现上述方法最简单的方式是以十六进制指定选项值并且追加四个零。所以下一个多事务号为(0000+1)*65536,最旧的多事务号为0000*65536。

                      • -o, --next-oid=OID       set next OID

                      参数是设置下一个OID(OID,object 是pg内部使用,作为系统表的主键),我们恢复时可以不设置这个参数,因为设置一个超过数据库中最大值OID没有好的办法。

                      • -O, --multixact-offset=OFFSET set next multitransaction offset

                      手工设置下一个多事务偏移量。

                      确定安全值的方法:**查找数据目录下pg_multixact/members目录中最大的数字文件名,然后在它的基础上加一并且乘以 52352 (0xCC80)。**文件名是十六进制数字。没有像其他选项那样追加零的简单方法。

                      • -x, --next-transaction-id=XID set next transaction ID

                      手工设置下一个事务 ID。

                      确定安全值的方法:在数据目录下的pg_xact目录中查找最大的数字文件名,然后在它的基础上加一并且乘以 1048576 (0x100000)。注意文件名是十六进制的数字。通常以十六进制的形式指定该选项值也是最容易的。例如,如果0011是pg_xact中的最大项,-x 0x1200000就可以(五个尾部的零就表示了前面说的乘数)

                      • --wal-segsize=SIZE     size of WAL segments, in megabytes

                      设置新的WAL段尺寸,以兆字节为单位。这个值必须被设为2的1次幂和10次幂(兆字节)之间。更多信息请参考initdb的相同选项。

                      注意虽然pg_resetwal将把WAL起始地址设置成超过最新的现有WAL段文件,但一些段尺寸的改变可能导致之前的WAL文件名被重用。如果WAL文件名重叠会导致归档策略出现问题,推荐把-l和这个选项一起使用来手动设置WAL起始地址。

                      参数设置新的WAL段大小,默认16M 。

                      实例如下:

                        pg_resetwal -c 0x00000,0x00000 -D /opt/pg12/pgdata -l 000000030000000A000000CA -m 0x10000,0x00001 -O 0xCC80 --wal-segsize=16 -x 0x100000

                        4、恢复实例

                        按照上边的方法,我们来实做一个恢复:

                        我们先把旧的pg_control文件重命名一下:

                          [15:28:56-postgres@centos2:/pgccc/pgdata/global]$ ls
                          1213 1214_fsm 1260 1261_fsm 1262_vm 2397 2677 2698 2965 3593 4176 4182 4186 6100 pg_filenode.map
                          1213_fsm 1214_vm 1260_fsm 1261_vm 2396 2671 2694 2846 2966 4060 4177 4183 6000 6114 pg_internal.init
                          1213_vm 1232 1260_vm 1262 2396_fsm 2672 2695 2847 2967 4061 4178 4184 6001 6115
                          1214 1233 1261 1262_fsm 2396_vm 2676 2697 2964 3592 4175 4181 4185 6002 pg_control
                          [15:28:57-postgres@centos2:/pgccc/pgdata/global]$ mv pg_control pg_control.0
                          [15:29:03-postgres@centos2:/pgccc/pgdata/global]$


                          [15:29:03-postgres@centos2:/pgccc/pgdata/global]$ pg_controldata
                          pg_controldata: fatal: could not open file "/pgccc/pgdata/global/pg_control" for reading: No such file or directory

                          4.1、计算命令行各项参数值

                          对着命令行:pg_resetwal -c {}} -D {} -l {} -m {} -O {}  --wal-segsize={} -x {}

                          仔细求证各项的值,以求恢复。

                          e.g.  pg_resetwal -c 0x00000,0x00000 -D $PGDATA  -l 000000030000000A000000CA -m 0x10000,0x00001 -O 0xCC80 --wal-segsize=16 -x 0x100000

                          1. -c 不用指定。因为目录下边没有文件。
                            检查对应目录下边的文件
                            [15:26:43-postgres@centos2:/pgccc/pgdata/pg_commit_ts]$ ls $PGDATA/pg_commit_ts
                            [15:26:53-postgres@centos2:/pgccc/pgdata/pg_commit_ts]$
                            1. -D  $PGDATA

                            这个比较明显。略。用环境变量即可。

                            1. -l  找出最新的WAL文件名: 00000001000000010000002C
                              [15:31:37-postgres@centos2:/pgccc/pgdata/pg_wal]$ ls
                              00000001000000010000002A 00000001000000010000002B archive_status

                              所以它的值应该是再+1,00000001000000010000002C

                              1. -m multitx的下一个,以及最旧的xid

                              找到目录:$PGDATA/pg_multixact/offsets,

                                [15:31:37-postgres@centos2:/pgccc/pgdata/pg_wal]$ cd $PGDATA/pg_multixact/offsets
                                [15:33:46-postgres@centos2:/pgccc/pgdata/pg_multixact/offsets]$ ls
                                0000

                                所以下一个值是:(0000+1)*65536,最旧的多事务号为0000*65536。

                                  postgres=# select to_hex(65536);
                                  to_hex
                                  --------
                                  10000
                                  (1 row)

                                  所以-m 后边的值应该是 -m  0x10000,0x00001

                                  1. -O 手工设置下一个多事务偏移量

                                  查找数据目录下pg_multixact/members目录中最大的数字文件名,然后在它的基础上加一并且乘以 52352 (0xCC80)。

                                    [11:24:28-postgres@centos2:/pgccc/pgdata/pg_wal]$ cd $PGDATA/pg_multixact/members
                                    [15:41:12-postgres@centos2:/pgccc/pgdata/pg_multixact/members]$ ls
                                    0000

                                    所以,它的值应该就是:52352,   -O 0xCC80

                                    1. -x 下一个事务ID

                                    在数据目录下的pg_xact目录中查找最大的数字文件名,然后在它的基础上加一并且乘以 1048576 (0x100000)。注意文件名是十六进制的数字。

                                      [15:41:13-postgres@centos2:/pgccc/pgdata/pg_multixact/members]$ cd $PGDATA/pg_xact
                                      [15:42:48-postgres@centos2:/pgccc/pgdata/pg_xact]$ ls
                                      0000

                                      这样得到的值应该是0x0100000,   -x 0x0100000

                                      1. --wal-segsize=

                                      这个比较容易, 直接查看大小,就能得知。

                                        [15:45:04-postgres@centos2:/pgccc/pgdata/pg_wal]$ ls -la
                                        total 32772
                                        drwx------. 3 postgres postgres 92 Dec 11 11:19 .
                                        drwx------. 20 postgres postgres 4096 Dec 11 12:01 ..
                                        -rw------- 1 postgres postgres 16777216 Dec 11 11:19 00000001000000010000002A
                                        -rw------- 1 postgres postgres 16777216 Dec 11 11:18 00000001000000010000002B
                                        drwx------. 2 postgres postgres 6 Dec 11 11:19 archive_status

                                        很明显,是16 (单位是MB)

                                        4.2、完整的命令行:

                                          pg_resetwal  -D $PGDATA -l 00000001000000010000002C -m 0x10000,0x00001 -O 0xCC80  --wal-segsize=16 -x 0x0100000 -f


                                          -- 跑一下这个命令,看看啥结果:
                                          [15:45:05-postgres@centos2:/pgccc/pgdata/pg_wal]$ pg_resetwal -D $PGDATA -l 00000001000000010000002C -m 0x10000,0x00001 -O 0xCC80 --wal-segsize=16 -x 0x0100000
                                          pg_resetwal: error: could not open file "global/pg_control" for reading: No such file or directory
                                          pg_resetwal: If you are sure the data directory path is correct, execute
                                          touch global/pg_control
                                          and try again.


                                          -- 还得有一个原来的文件之类的, touch一个pg_control空文件:
                                          [15:49:04-postgres@centos2:/pgccc/pgdata/global]$ cp pg_control.0 pg_control


                                          [15:58:12-postgres@centos2:/pgccc/pgdata/global]$ rm -f pg_control
                                          [15:58:22-postgres@centos2:/pgccc/pgdata/global]$ touch pg_control




                                          [15:49:12-postgres@centos2:/pgccc/pgdata/global]$ pg_resetwal -D $PGDATA -l 00000001000000010000002C -m 0x10000,0x00001 -O 0xCC80 --wal-segsize=16 -x 0x0100000
                                          The database server was not shut down cleanly.
                                          Resetting the write-ahead log might cause data to be lost.
                                          If you want to proceed anyway, use -f to force reset.


                                          -- 要-f强制:
                                          [15:49:21-postgres@centos2:/pgccc/pgdata/global]$ [15:59:29-postgres@centos2:/pgccc/pgdata/global]$ pg_resetwal -D $PGDATA -l 00000001000000010000002D -m 0x10000,0x00001 -O 0xCC80 --wal-segsize=16 -x 0x0100000 -f
                                          pg_resetwal: warning: pg_control exists but is broken or wrong version; ignoring it
                                          Write-ahead log reset

                                          reset结束,我们看看系统能启动不?

                                          4.3、检验下控制文件内容:

                                            [15:49:52-postgres@centos2:/pgccc/pgdata/global]$ pg_controldata
                                            pg_control version number: 1300
                                            Catalog version number: 202107181
                                            Database system identifier: 7138432685960386315
                                            Database cluster state: shut down
                                            pg_control last modified: Sun 11 Dec 2022 03:49:51 PM CST
                                            Latest checkpoint location: 1/2C000028
                                            Latest checkpoint's REDO location: 1/2C000028
                                            Latest checkpoint's REDO WAL file: 00000001000000010000002C
                                            Latest checkpoint's TimeLineID: 1
                                            Latest checkpoint's PrevTimeLineID: 1
                                            Latest checkpoint's full_page_writes: on
                                            Latest checkpoint's NextXID: 0:1048576
                                            Latest checkpoint's NextOID: 31466
                                            Latest checkpoint's NextMultiXactId: 65536
                                            Latest checkpoint's NextMultiOffset: 52352
                                            Latest checkpoint's oldestXID: 727
                                            Latest checkpoint's oldestXID's DB: 1
                                            Latest checkpoint's oldestActiveXID: 1461
                                            Latest checkpoint's oldestMultiXid: 1
                                            Latest checkpoint's oldestMulti's DB: 0
                                            Latest checkpoint's oldestCommitTsXid:0
                                            Latest checkpoint's newestCommitTsXid:0
                                            Time of latest checkpoint: Sun 11 Dec 2022 03:49:51 PM CST
                                            Fake LSN counter for unlogged rels: 0/3E8
                                            Minimum recovery ending location: 0/0
                                            Min recovery ending loc's timeline: 0
                                            Backup start location: 0/0
                                            Backup end location: 0/0
                                            End-of-backup record required: no
                                            wal_level setting: minimal
                                            wal_log_hints setting: off
                                            max_connections setting: 100
                                            max_worker_processes setting: 8
                                            max_wal_senders setting: 10
                                            max_prepared_xacts setting: 0
                                            max_locks_per_xact setting: 64
                                            track_commit_timestamp setting: off
                                            Maximum data alignment: 8
                                            Database block size: 8192
                                            Blocks per segment of large relation: 131072
                                            WAL block size: 8192
                                            Bytes per WAL segment: 16777216
                                            Maximum length of identifiers: 64
                                            Maximum columns in an index: 32
                                            Maximum size of a TOAST chunk: 1996
                                            Size of a large-object chunk: 2048
                                            Date/time type storage: 64-bit integers
                                            Float8 argument passing: by value
                                            Data page checksum version: 0
                                            Mock authentication nonce: aaa8abf569631ec60ba05e3f625495da70007738b831e46e1cfda0d26c370987

                                            4.4、重启实例

                                              [15:50:17-postgres@centos2:/pgccc/pgdata/global]$ pg_ctl start
                                              waiting for server to start....2022-12-11 15:52:01.999 CST [7169] LOG: redirecting log output to logging collector process
                                              2022-12-11 15:52:01.999 CST [7169] HINT: Future log output will appear in directory "log".
                                              done
                                              server started


                                              对应的日志:
                                              [15:51:53-postgres@centos2:/var/lib/pgsql/14/data/log]$ tail -f postgresql-2022-12-11.log
                                              2022-12-11 11:16:29.517 CST [4638] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5555"
                                              2022-12-11 11:16:29.519 CST [4638] LOG: listening on Unix socket "/tmp/.s.PGSQL.5555"
                                              2022-12-11 11:16:29.522 CST [4640] LOG: database system was interrupted; last known up at 2022-12-11 11:13:58 CST
                                              2022-12-11 11:16:29.537 CST [4640] LOG: database system was not properly shut down; automatic recovery in progress
                                              2022-12-11 11:16:29.538 CST [4640] LOG: redo starts at 1/28000200
                                              2022-12-11 11:16:29.585 CST [4640] LOG: invalid record length at 1/28629D08: wanted 24, got 0
                                              2022-12-11 11:16:29.585 CST [4640] LOG: redo done at 1/28629CE0 system usage: CPU: user: 0.03 s, system: 0.00 s, elapsed: 0.04 s
                                              2022-12-11 11:16:29.604 CST [4638] LOG: database system is ready to accept connections
                                              2022-12-11 11:19:46.756 CST [4638] LOG: received immediate shutdown request
                                              2022-12-11 11:19:46.762 CST [4638] LOG: database system is shut down
                                              2022-12-11 15:52:01.999 CST [7169] LOG: starting PostgreSQL 14.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
                                              2022-12-11 15:52:01.999 CST [7169] LOG: listening on IPv4 address "0.0.0.0", port 5555
                                              2022-12-11 15:52:02.001 CST [7169] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5555"
                                              2022-12-11 15:52:02.003 CST [7169] LOG: listening on Unix socket "/tmp/.s.PGSQL.5555"
                                              2022-12-11 15:52:02.007 CST [7171] LOG: database system was shut down at 2022-12-11 15:49:51 CST
                                              2022-12-11 15:52:02.021 CST [7169] LOG: database system is ready to accept connections

                                              成功的启动了。

                                              再重新看看control文件的信息:

                                                [15:52:02-postgres@centos2:/pgccc/pgdata/global]$ pg_controldata $PGDATA
                                                pg_control version number: 1300
                                                Catalog version number: 202107181
                                                Database system identifier: 7138432685960386315
                                                Database cluster state: in production
                                                pg_control last modified: Sun 11 Dec 2022 03:52:02 PM CST
                                                Latest checkpoint location: 1/2C000028
                                                Latest checkpoint's REDO location: 1/2C000028
                                                Latest checkpoint's REDO WAL file: 00000001000000010000002C
                                                Latest checkpoint's TimeLineID: 1
                                                Latest checkpoint's PrevTimeLineID: 1
                                                Latest checkpoint's full_page_writes: on
                                                Latest checkpoint's NextXID: 0:1048576
                                                Latest checkpoint's NextOID: 31466
                                                Latest checkpoint's NextMultiXactId: 65536
                                                Latest checkpoint's NextMultiOffset: 52352
                                                Latest checkpoint's oldestXID: 727
                                                Latest checkpoint's oldestXID's DB: 1
                                                Latest checkpoint's oldestActiveXID: 1461
                                                Latest checkpoint's oldestMultiXid: 1
                                                Latest checkpoint's oldestMulti's DB: 0
                                                Latest checkpoint's oldestCommitTsXid:0
                                                Latest checkpoint's newestCommitTsXid:0
                                                Time of latest checkpoint: Sun 11 Dec 2022 03:49:51 PM CST
                                                Fake LSN counter for unlogged rels: 0/3E8
                                                Minimum recovery ending location: 0/0
                                                Min recovery ending loc's timeline: 0
                                                Backup start location: 0/0
                                                Backup end location: 0/0
                                                End-of-backup record required: no
                                                wal_level setting: replica
                                                wal_log_hints setting: off
                                                max_connections setting: 100
                                                max_worker_processes setting: 8
                                                max_wal_senders setting: 10
                                                max_prepared_xacts setting: 0
                                                max_locks_per_xact setting: 64
                                                track_commit_timestamp setting: off
                                                Maximum data alignment: 8
                                                Database block size: 8192
                                                Blocks per segment of large relation: 131072
                                                WAL block size: 8192
                                                Bytes per WAL segment: 16777216
                                                Maximum length of identifiers: 64
                                                Maximum columns in an index: 32
                                                Maximum size of a TOAST chunk: 1996
                                                Size of a large-object chunk: 2048
                                                Date/time type storage: 64-bit integers
                                                Float8 argument passing: by value
                                                Data page checksum version: 0
                                                Mock authentication nonce: aaa8abf569631ec60ba05e3f625495da70007738b831e46e1cfda0d26c370987
                                                  [16:00:25-postgres@centos2:/pgccc/pgdata/pg_wal]$ ls
                                                  00000001000000010000002F archive_status
                                                  [16:00:26-postgres@centos2:/pgccc/pgdata/pg_wal]$

                                                  文章转载自数据库杂记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                  评论