PostgreSQL最后的救命稻草 — pg_resetwal

Posted PostgreSQLChina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL最后的救命稻草 — pg_resetwal相关的知识,希望对你有一定的参考价值。

pg_resetwal— 重置 PostgreSQL 数据库集群的预写日志和其他控制信息

适用版本:PostgreSQL 12/13/14/15

语法

pg_resetwal [ -f | --force ] [ -n | --dry-run ] [option...] [ -D | --pgdata ]datadir

描述
pg_resetwal清除预写日志 WAL,并可选地重置pg_control文件中的一些其他控制信息。当 WAL 文件或 pg_control 控制文件损坏时,导致数据库无法启动时,该操作将作为数据库修复的最后手段使用。

通过 pg_resetwal 修复而启动数据库后,可能会由于部分提交的事务,导致数据库可能存在数据不一致的情况。所以,应该立即转储数据,建议重新初始化新的数据库恢复。恢复后再检查不一致,并根据需要进一步修复。

pg_resetwal只能由安装数据库用户运行,因为它需要对数据目录进行读/写访问。注意:考虑安全原因,pg_resetwal不使用环境变量 PGDATA,所以必须在命令行上指定数据目录。

如果 pg_resetwal 提示无法确定pg_control的有效数据,可以通过指定-f(force)选项强制继续执行。大多数字段可以自动匹配,但下一个OID、下一个事务ID和epoch、下一多事务ID和偏移量以及WAL起始位置字段值可能需要手动指定。可以使用一些选项设置这些字段值。如果无法确定这些字段的正确值,也可使用-f,但必须对恢复的数据库更为严谨的处理:必须立即转储和恢复。在转储之前,不要在数据库中执行任何数据修改操作,因为任何此类操作都可能会使损坏更严重。

命令帮助

  [postgres@lyp ~]$ pg_resetwal --help
    pg_resetwal resets the PostgreSQL write-ahead log.
    Usage:
      pg_resetwal [OPTION]... DATADIR
    Options:
      -c, --commit-timestamp-ids=XID,XID    设置带有提交时间戳的最早和最新事务(零表示没有更改)
     [-D, --pgdata=]DATADIR                  数据目录
      -e, --epoch=XIDEPOCH                   设置下一个事务ID纪元epoch
      -f, --force                            强制更新完成
      -l, --next-wal-file=WALFILE            设置新WAL的最小起始位置
      -m, --multixact-ids=MXID,MXID          设置下一个和最旧的多事务ID
      -n, --dry-run                          没有更新,只显示将要执行的操作
      -o, --next-oid=OID                     设置下一个OID
      -O, --multixact-offset=OFFSET          设置下一个多事务偏移量
      -V, --version                          输出版本信息,然后退出
      -x, --next-transaction-id=XID          设置下一个事务ID
          --wal-segsize=SIZE                 WAL段的大小(MB)
      -?, --help                             
    Report bugs to <pgsql-bugs@lists.postgresql.org>.
    PostgreSQL home page: <https://www.postgresql.org/>
    [postgres@lyp ~]$

选项详解

只有当 pg_resetwal 无法通过读取pg_control 来确定适当的值时,才需要以下选项。对于采用数字参数的值,可以使用前缀0x指定十六进制值。

    -c xid1,xid2
    —commit-timestamp-ids=xid1,xid2

手动设置可以检索提交时间的最旧和最新事务ID。

xid1:可以通过在 $PGDATA/pg_commit_ts 目录中查找数值最小的文件名来确定可以检索提交时间的最旧事务ID的安全值(第一部分)。xid2:相反,可以通过在同一目录中查找数值最大的文件名来确定可以检索提交时间的最新事务ID的安全值。文件名为十六进制。

    -e xid_epoch
    —epoch=xid_epoch

手动设置下一个事务ID的epoch。

事务ID epoch实际上并没有保存在数据库中的任何位置,除非存储在由pg_resetwal设置的字段中,因此就数据库本身而言,任何值都是有效的。您可能需要调整此值,以确保复制系统(如Slony-I和Skytools)正常工作-如果是这样,应该可以从下游复制数据库的状态获得适当的值。

    -l walfile
    —next-wal-file=walfile

通过指定下一个WAL段文件的名称,手动设置WAL起始位置。

可以通过 $PGDATA/pg_wal 目录中查找数值最新的WAL段的文件名,+1。这些名称也是十六进制的,有三个部分。第一部分是“时间线ID”,通常应保持不变。例如,如果0000000100000009000000B7是pg_wal中最大的条目,请使用-l 0000000100000009000000B8 或更高。

注意,当使用非默认WAL段大小时,WAL文件名中的数字与系统函数和系统视图报告的LSN不同。此选项采用WAL文件名,而不是LSN。

格式:-l 0000000100000009000000B8

    -m mxid1,mxid2
    —multixact-ids=mxid1,mxid2

手动设置下一个和最旧的多事务ID。

mxid1:下一个多事务ID的安全值可以通过在 $PGDATA/pg_multixact/offsets 目录中查找数值最大的文件名,+1,然后乘以65536(0x10000)来确定。mxid2:相反,最旧的多事务ID的安全值可以通过 $PGDATA/pg_multixact/offsets 目录中数字最小的文件名,乘以65536来确定。文件名是十六进制的,因此最简单的方法是以十六进制指定选项值并附加四个零。

注意:若当前值为0,那么mxid2亦为0,则mxid2取mxid1的值。

格式:-m 0x10000, 0x100000

    -o oid
    —next-oid=oid

手动设置下一个OID。

没有相对简单的方法来确定下一个超出数据库中最大OID的OID,但幸运的是,正确设置下一个OID并不重要。

    -O mxoff
    —multixact-offset=mxoff

手动设置下一个多事务处理偏移量。

安全值可以通过在 $PGDATA/pg_multixact/members 目录中查找数值最大的文件名,+1,然后乘以52352(0xCC80)来确定。文件名为十六进制。没有像附加零的其他选项那样的简单方法。

若找到最大值0000,+1,乘以 52352 (0xCC80),这个需要进行计算,没有简单的加0的方法。格式:0xCC80

若找到最大值00C1(193),+1,乘以 52352 (0xCC80)。最后得值:(193+1)* 52352 = 4918288。16进制为:4B0C10,结果为:0x004B0C10

   —wal-segsize=wal_segment_size

设置新的WAL段大小(MB)。该值必须设置为介于1和1024(兆字节)之间的2的幂。

虽然pg_resetwal会将WAL起始地址设置在最新的现有WAL段文件之外,但某些段大小的更改可能会导致重用以前的WAL文件名。如果WAL文件名重叠会导致归档策略出现问题,建议将-l与此选项一起使用以手动设置WAL起始地址。

    -u xid
    —oldest-transaction-id=xid

手动设置最旧的未冻结交易ID。

可以通过在 $PGDATA/pg_xact 目录中查找数值最小的文件名,然后乘以1048576(0x100000)来确定安全值。请注意,文件名是十六进制的,因此最简单的方法是以十六进制指定选项值并附加五个零。例如,如果0007是pg_xact中最小的条目,-u 0x700000将起作用。

    -x xid
    —next-transaction-id=xid

手动设置下一个事务ID。

安全值可以通过在 $PGDATA/pg_xact 目录中查找数值最大的文件名,+1,然后乘以1048576(0x100000)来确定。请注意,文件名是十六进制的。,因此最简单的方法是以十六进制指定选项值并附加五个零。例如,如果0011是pg_xact中最大的条目,-x 0x1200000将起作用(五个尾随零提供正确的乘数)。

使用案例
pg_resetwal 用于丢失一些文件导致数据库无法启动进行修复。需要再次强调,pg_resetwal并不是日常使用的工具,是数据库最后的修复手段。常规性恢复请使用常规手段进行。

使用 pg_resetwal 修复的数据库,一般会正常启动,但是可能会因为参数的不准确而导致数据库存在其他异常问题。

如果因为丢失WAL文件导致数据库不一致,或者控制文件丢失,那么我们只需要通过这个工具生成一个最新的文件就可以强制打开数据库了。

重置WAL

创建测试数据

    [postgres@lyp pg_wal]$ psql
    psql (14.1)
    Type "help" for help.
    postgres=# create table lxs1(id int);
    CREATE TABLE
    postgres=# insert into lxs1 values(1);
    INSERT 0 1
    postgres=# insert into lxs1 values(2);
    INSERT 0 1
    postgres=# checkpoint;
    CHECKPOINT
    postgres=# insert into lxs1 values(3);
    INSERT 0 1
    postgres=#

模拟数据库异常

    [postgres@lyp pg_wal]$ ps -ef |grep postgres
    root      19555  13684  0 16:49 pts/1    00:00:00 su - postgres
    postgres  19556  19555  0 16:49 pts/1    00:00:00 -bash
    postgres  19767  19556  0 16:52 pts/1    00:00:00 psql
    root      19790  18013  0 16:53 pts/2    00:00:00 su - postgres
    postgres  19791  19790  0 16:53 pts/2    00:00:00 -bash
    postgres  19865      1  0 16:54 ?        00:00:00 /opt/pgsql14.1/bin/postgres
    postgres  19866  19865  0 16:54 ?        00:00:00 postgres: logger
    postgres  19868  19865  0 16:54 ?        00:00:00 postgres: checkpointer
    postgres  19869  19865  0 16:54 ?        00:00:00 postgres: background writer
    postgres  19870  19865  0 16:54 ?        00:00:00 postgres: walwriter
    postgres  19871  19865  0 16:54 ?        00:00:00 postgres: autovacuum launcher
    postgres  19872  19865  0 16:54 ?        00:00:00 postgres: archiver failed on 000000010000000000000012
    postgres  19873  19865  0 16:54 ?        00:00:00 postgres: stats collector
    postgres  19874  19865  0 16:54 ?        00:00:00 postgres: logical replication launcher
    postgres  19883  19865  0 16:55 ?        00:00:00 postgres: postgres postgres [local] idle
    postgres  19899  19791  0 16:55 pts/2    00:00:00 ps -ef
    postgres  19900  19791  0 16:55 pts/2    00:00:00 grep --color=auto postgres
    [postgres@lyp pg_wal]$ kill -9 19865
    [postgres@lyp pg_wal]$ ps -ef |grep postgres
    root      19555  13684  0 16:49 pts/1    00:00:00 su - postgres
    postgres  19556  19555  0 16:49 pts/1    00:00:00 -bash
    postgres  19767  19556  0 16:52 pts/1    00:00:00 psql
    root      19790  18013  0 16:53 pts/2    00:00:00 su - postgres
    postgres  19791  19790  0 16:53 pts/2    00:00:00 -bash
    postgres  19901  19791  0 16:55 pts/2    00:00:00 ps -ef
    postgres  19902  19791  0 16:55 pts/2    00:00:00 grep --color=auto postgres
    [postgres@lyp pg_wal]$

删除WAL文件

    [postgres@lyp ~]$ cd $PGDATA/pg_wal
    [postgres@lyp pg_wal]$ ls -lrt
    total 196620
    -rw-------. 1 postgres postgres 16777216 Feb 21  2022 000000010000000000000007
    -rw-------. 1 postgres postgres 16777216 Feb 21  2022 000000010000000000000008
    -rw-------. 1 postgres postgres      345 Feb 21  2022 000000010000000000000008.00000028.backup
    -rw-------. 1 postgres postgres 16777216 Feb 22  2022 000000010000000000000009
    -rw-------. 1 postgres postgres 16777216 Feb 22  2022 00000001000000000000000A
    -rw-------. 1 postgres postgres      318 Feb 22  2022 00000001000000000000000A.00000028.backup
    -rw-------. 1 postgres postgres 16777216 Feb 24  2022 00000001000000000000000B
    -rw-------. 1 postgres postgres 16777216 Feb 24  2022 00000001000000000000000C
    -rw-------. 1 postgres postgres 16777216 Feb 25  2022 00000001000000000000000D
    -rw-------. 1 postgres postgres 16777216 May 10  2022 00000001000000000000000E
    -rw-------. 1 postgres postgres 16777216 Nov 19 23:13 00000001000000000000000F
    -rw-------. 1 postgres postgres 16777216 Nov 26 18:21 000000010000000000000010
    -rw-------. 1 postgres postgres 16777216 Mar 13 16:52 000000010000000000000011
    -rw-------. 1 postgres postgres 16777216 Mar 13 16:52 000000010000000000000012
    drwx------. 2 postgres postgres     4096 Mar 13 16:52 archive_status
    -rw-------. 1 postgres postgres 16777216 Mar 13 16:52 000000010000000000000013
    [postgres@lyp pg_wal]$
    [postgres@lyp pg_wal]$ rm -rf 0000000100000000000000*
    [postgres@lyp pg_wal]$
    [postgres@lyp pg_wal]$ ls -lrt
    total 4
    drwx------. 2 postgres postgres 4096 Mar 13 16:52 archive_status
    [postgres@lyp pg_wal]$

尝试启动数据库

    [postgres@lyp pg_wal]$ pg_ctl start
    pg_ctl: another server might be running; trying to start server anyway
    waiting for server to start....2023-03-13 16:56:07.956 CST [19916] LOG:  redirecting log output to logging collector process
    2023-03-13 16:56:07.956 CST [19916] HINT:  Future log output will appear in directory "log".
     stopped waiting
    pg_ctl: could not start server
    Examine the log output.
    [postgres@lyp pg_wal]$

重置WAL

    [postgres@lyp pg_wal]$ pg_resetwal $PGDATA
    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.
    [postgres@lyp pg_wal]$ pg_resetwal -f $PGDATA
    Write-ahead log reset
    [postgres@lyp pg_wal]$ ls -lrt
    total 16384
    drwx------. 2 postgres postgres        6 Mar 13 17:03 archive_status
    -rw-------. 1 postgres postgres 16777216 Mar 13 17:03 000000010000000000000014
    [postgres@lyp pg_wal]$

启动数据库

    [postgres@lyp pg_wal]$ pg_ctl start
    waiting for server to start....2023-03-13 17:04:10.205 CST [20173] LOG:  redirecting log output to logging collector process
    2023-03-13 17:04:10.205 CST [20173] HINT:  Future log output will appear in directory "log".
     done
    server started
    [postgres@lyp pg_wal]$ psql
    psql (14.1)
    Type "help" for help.
    postgres=# select * from lxs1;
     id
    ----
      1
      2
    (2 rows)
    postgres=#

可以看到测试数据中 checkpoint 检查点后的数据,由于WAL重置而丢失。

重建控制文件

创建测试数据

    [postgres@lyp pg_wal]$ psql
    psql (14.1)
    Type "help" for help.
    postgres=# drop table lxs1;
    DROP TABLE
    postgres=# create table lxs1(id int);
    CREATE TABLE
    postgres=# insert into lxs1 values(1);
    INSERT 0 1
    postgres=# insert into lxs1 values(2);
    INSERT 0 1
    postgres=# checkpoint;
    CHECKPOINT
    postgres=# insert into lxs1 values(3);
    INSERT 0 1
    postgres=#

模拟数据库异常

    [postgres@lyp pg_wal]$ ps -ef |grep postgres
    root      19555  13684  0 16:49 pts/1    00:00:00 su - postgres
    postgres  19556  19555  0 16:49 pts/1    00:00:00 -bash
    postgres  19767  19556  0 16:52 pts/1    00:00:00 psql
    root      19790  18013  0 16:53 pts/2    00:00:00 su - postgres
    postgres  19791  19790  0 16:53 pts/2    00:00:00 -bash
    root      19965  19924  0 16:56 pts/0    00:00:00 su - postgres
    postgres  19966  19965  0 16:56 pts/0    00:00:00 -bash
    postgres  20013  19966  0 16:56 pts/0    00:00:00 tail -100f postgresql-2023-03-13_072.log
    postgres  20272      1  0 17:08 ?        00:00:00 /opt/pgsql14.1/bin/postgres
    postgres  20273  20272  0 17:08 ?        00:00:00 postgres: logger
    postgres  20275  20272  0 17:08 ?        00:00:00 postgres: checkpointer
    postgres  20276  20272  0 17:08 ?        00:00:00 postgres: background writer
    postgres  20277  20272  0 17:08 ?        00:00:00 postgres: walwriter
    postgres  20278  20272  0 17:08 ?        00:00:00 postgres: autovacuum launcher
    postgres  20279  20272  0 17:08 ?        00:00:00 postgres: archiver failed on 000000010000000000000015
    postgres  20280  20272  0 17:08 ?        00:00:00 postgres: stats collector
    postgres  20281  20272  0 17:08 ?        00:00:00 postgres: logical replication launcher
    postgres  20288  20272  0 17:08 ?        00:00:00 postgres: postgres postgres [local] idle
    postgres  20359  19791  0 17:10 pts/2    00:00:00 ps -ef
    postgres  20360  19791  0 17:10 pts/2    00:00:00 grep --color=auto postgres
    [postgres@lyp pg_wal]$ kill -9 20272
    [postgres@lyp pg_wal]$ ps -ef |grep postgres
    root      19555  13684  0 16:49 pts/1    00:00:00 su - postgres
    postgres  19556  19555  0 16:49 pts/1    00:00:00 -bash
    postgres  19767  19556  0 16:52 pts/1    00:00:00 psql
    root      19790  18013  0 16:53 pts/2    00:00:00 su - postgres
    postgres  19791  19790  0 16:53 pts/2    00:00:00 -bash
    root      19965  19924  0 16:56 pts/0    00:00:00 su - postgres
    postgres  19966  19965  0 16:56 pts/0    00:00:00 -bash
    postgres  20013  19966  0 16:56 pts/0    00:00:00 tail -100f postgresql-2023-03-13_072.log
    postgres  20361  19791  0 17:11 pts/2    00:00:00 ps -ef
    postgres  20362  19791  0 17:11 pts/2    00:00:00 grep --color=auto postgres
    [postgres@lyp pg_wal]$

破坏控制文件

    [postgres@lyp pg_wal]$ cd $PGDATA/global
    [postgres@lyp global]$ ls -rlt pg_control
    -rw-------. 1 postgres postgres 8192 Mar 13 17:08 pg_control
    [postgres@lyp global]$ echo "" >pg_control
    [postgres@lyp global]$ ls -rlt pg_control
    -rw-------. 1 postgres postgres 1 Mar 13 17:12 pg_control
    [postgres@lyp global]$

尝试启动数据库

    [postgres@lyp global]$ pg_ctl start
    pg_ctl: another server might be running; trying to start server anyway
    waiting for server to start....2023-03-13 17:13:06.788 CST [20419] PANIC:  could not read file "global/pg_control": read 1 of 296
     stopped waiting
    pg_ctl: could not start server
    Examine the log output.
    [postgres@lyp global]$

重建控制文件

pg_resetwal 重建控制文件,需要参数如下:

    -l walfile
    —next-wal-file=walfile

通过指定下一个WAL段文件的名称,手动设置WAL起始位置。

可以通过 $PGDATA/pg_wal 目录中查找数值最新的WAL段的文件名,+1。

        [postgres@lyp global]$ cd $PGDATA/pg_wal
        [postgres@lyp pg_wal]$ ls -lrt
        total 32768
        -rw-------. 1 postgres postgres 16777216 Mar 13 17:08 000000010000000000000015
        drwx------. 2 postgres postgres       44 Mar 13 17:08 archive_status
        -rw-------. 1 postgres postgres 16777216 Mar 13 17:09 000000010000000000000016
        [postgres@lyp pg_wal]$

当前 000000010000000000000016 是pg_wal中最大的条目,则使用-l 000000010000000000000017  

    -m mxid1,mxid2
    —multixact-ids=mxid1,mxid2

手动设置下一个和最旧的多事务ID。

mxid1:下一个多事务ID的安全值可以通过在 $PGDATA/pg_multixact/offsets 目录中查找数值最大的文件名,+1,然后乘以65536(0x10000)来确定。mxid2:相反,最旧的多事务ID的安全值可以通过$PGDATA/pg_multixact/offsets目录中数字最小的文件名,乘以65536来确定。文件名是十六进制的,因此最简单的方法是以十六进制指定选项值并附加四个零。

注意:若当前值为0,那么mxid2亦为0,则mxid2取mxid1的值。

        postgres@lyp offsets]$ ls -lrt
        total 8
        -rw-------. 1 postgres postgres 8192 Mar 13 17:08 0000
        [postgres@lyp offsets]$

当前值为0000,则mxid1为:0x10000,mxid2取mxid1的值,则使用-m 0x10000,0x10000

    -O mxoff
    —multixact-offset=mxoff

 手动设置下一个多事务处理偏移量。

安全值可以通过在 $PGDATA/pg_multixact/members 目录中查找数值最大的文件名,+1,然后乘以52352(0xCC80)来确定。文件名为十六进制。没有像附加零的其他选项那样的简单方法。

  [postgres@lyp members]$ ls -rlt
  total 8
  -rw-------. 1 postgres postgres 8192 Feb 21  2022 0000
  [postgres@lyp members]$

 当前值为0000,则使用 -O 0xCC80  

    -x xid
    —next-transaction-id=xid

手动设置下一个事务ID。

 安全值可以通过在$PGDATA/pg_xact目录中查找数值最大的文件名,+1,然后乘以1048576(0x100000)来确定。请注意,文件名是十六进制的。,因此最简单的方法是以十六进制指定选项值并附加五个零。

 [postgres@lyp members]$ cd $PGDATA/pg_xact
 [postgres@lyp pg_xact]$ ls -rlt
 total 8
 -rw-------. 1 postgres postgres 8192 Mar 13 17:08 0000
 [postgres@lyp pg_xact]$

 当前值为0000,则使用- x 0x100000   

重建控制文件

        [postgres@lyp global]$ pg_resetwal -l 000000010000000000000017 -m 0x10000,0x10000 -O 0xCC80 -x 0x100000 $PGDATA
        pg_resetwal: error: lock file "postmaster.pid" exists
        pg_resetwal: Is a server running?  If not, delete the lock file and try again.
        [postgres@lyp global]$

 由于是数据异常关闭,所以存在锁文件,删除后重新执行。

        [postgres@lyp global]$ ls -rlt $PGDATA/postmaster.pid
        -rw-------. 1 postgres postgres 39 Mar 13 17:13 /opt/pgdata14.1/postmaster.pid
        [postgres@lyp global]$ rm -rf  $PGDATA/postmaster.pid
        [postgres@lyp global]$ pg_resetwal -l 000000010000000000000017 -m 0x10000,0x10000 -O 0xCC80 -x 0x100000 $PGDATA
        pg_resetwal: warning: pg_control exists but is broken or wrong version; ignoring it
        Guessed pg_control values:
        pg_control version number:            1300
        Catalog version number:               202107181
        Database system identifier:           7209963927373898017
        Latest checkpoint's TimeLineID:       1
        Latest checkpoint's full_page_writes: off
        Latest checkpoint's NextXID:          0:3
        Latest checkpoint's NextOID:          12000
        Latest checkpoint's NextMultiXactId:  1
        Latest checkpoint's NextMultiOffset:  0
        Latest checkpoint's oldestXID:        3
        Latest checkpoint's oldestXID's DB:   0
        Latest checkpoint's oldestActiveXID:  0
        Latest checkpoint's oldestMultiXid:   1
        Latest checkpoint's oldestMulti's DB: 0
        Latest checkpoint's oldestCommitTsXid:0
        Latest checkpoint's newestCommitTsXid:0
        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
        Values to be changed:
        First log segment after reset:        000000010000000000000017
        NextMultiXactId:                      65536
        OldestMultiXid:                       65536
        OldestMulti's DB:                     0
        NextMultiOffset:                      52352
        NextXID:                              1048576
        OldestXID:                            3
        OldestXID's DB:                       0
        If these values seem acceptable, use -f to force reset.
        [postgres@lyp global]$
        [postgres@lyp global]$ pg_resetwal -l 000000010000000000000017 -m 0x10000,0x10000 -O 0xCC80 -x 0x100000 $PGDATA -f
        pg_resetwal: warning: pg_control exists but is broken or wrong version; ignoring it
        Write-ahead log reset
        [postgres@lyp global]$
        [postgres@lyp global]$ ls -rlt pg_control
        -rw-------. 1 postgres postgres 8192 Mar 13 17:43 pg_control
        [postgres@lyp global]$

启动数据库

    [postgres@lyp global]$ pg_ctl start
    waiting for server to start....2023-03-13 17:44:00.209 CST [20785] LOG:  redirecting log output to logging collector process
    2023-03-13 17:44:00.209 CST [20785] HINT:  Future log output will appear in directory "log".
     done
    server started
    [postgres@lyp global]$ psql
    psql (14.1)
    Type "help" for help.
    postgres=# select * from lxs1;
     id
    ----
      1
      2
    (2 rows)
    postgres=#

可以看到测试数据中 checkpoint 检查点后的数据,由于控制文件重置而丢失。

注意

1、注意据库正在运行时,不得使用此命令。
2、如果 pg_resetwal 在数据目录中找到服务器锁定文件,将启动失败。
3、如果数据库已崩溃,那么可能会留下一个锁文件(postmaster.pid);在这种情况下,可以删除锁定文件以保证 postmaster.pid 的正常运行。但在此操作之前,需要再次确保没有数据库进程在运行。
4、pg_resetwal仅适用于相同主版本的数据库服务器。

2020蓝桥杯救命稻草--之救命15题

2020蓝桥杯救命稻草

第一阶段:基础知识(对标省三)
Step1:基本语法(流程,控制,循环)
(半小时内独立解决“打印图形”&“数的分解”可以跳过此Step)
(拓展:用有限变量解决“斐波那契”问题。)
Step2:JavaAPI(排序,容器,字符串,大数)
(半小时内独立解决“日志统计”&“复数幂”可以跳过此Step)
(拓展:解决“人物相关性分析”部分问题。)
第二阶段:能力提升(对标省二)
Step3:数组(前缀和,差分,简单DP)
(一小时内独立解决“最大下降矩阵”&“校门外的树”可以跳过此Step)
(拓展:解决“人物相关性分析”问题。)
Step4:函数(质数筛,汉诺塔,快速幂)
(一小时内独立解决“哥德巴赫猜想”&“大数运算”可以跳过此Step)(39级台阶)
(拓展:解决“经典汉诺塔”问题。)
第三阶段:暴力美学(对标省一)
Step5:暴力破解一(全排列,二分)
(一小时内独立解决“瓜分种数”&“分巧克力”可以跳过此Step)
Step6:暴力破解二(DFS,BFS)
(一小时内独立解决“全球变暖”&“迷宫求解”可以跳过此Step)
第四阶段:考试技巧(提升大概1~2个等级)
Step7:技巧篇(无)

  • 注:精选蓝桥思维算法15道,且有对标水准,几乎涵盖所有会用到的思想和算法,后边题目难度较大,恳请对代码指正优化

Step1:基本语法(流程,控制,循环)

1.“打印图形”

打印图形
时间限制: 1.0s   内存限制: 512.0MB
【问题描述】
小明刚学习完条件语句和循环语句,并且也打印了许多图形,比如菱形或者三角形。然后他突发奇想要打印一个六芒星,果然,他用了半小时就把六芒星给打印出来了,你能比他更快吗?小明为你加油哦!
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一个六芒星,表示满足题意的图形。
【样例输入】
3
4
【样例输出】
   

 
  
【评测用例规模与约定】  
对于所有评测用例,1 ≤ n ≤ 20
import java.util.Scanner;
public class A_PrintSixPointStar 
	public static void main(String[] args) 
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		if(n == 1)
			System.out.print('*');
		else if (n > 1 && n <= 20) 
			int i = 4 * n - 3;
			int j = 6 * n - 5;
			char arr[][] = new char[i][j];
			for(int a = 0; a < arr.length; a ++) 
				for(int b = 0; b < arr[1].length; b ++) 	
					if (a < n - 1) 
						arr[a][(3 * n - 3) - a] = '*';
						arr[a][(3 * n - 3) + a] = '*';
					
					else if (a == n - 1 && b % 2 == 0)
						arr[a][b] = '*';
					else if (a > n - 1 && a <= 2 * n - 2) 
						arr[a][a - n + 1] = '*';
						arr[a][3 * n - 3 - a] = '*';
						arr[a][3 * n - 3 + a] = '*';
						arr[a][7 * n - 7 - a] = '*';	
							
					else if(a > 2 * n - 2)
						arr[a][b] = arr[4 * n - a - 4][b];
					else
						arr[a][b] = ' ';	
				
			for (int k = 0; k < arr.length; k++) 
				for (int k2 = 0; k2 < arr[1].length; k2++)
					System.out.print(arr[k][k2]);
				System.out.println();
					
		
	

2.“数的分解”

 								数的分解
时间限制: 1.0s   内存限制: 512.0MB
【问题描述】
把 n分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包
含数字  24,一共有多少种不同的分解方法?
注意交换 3 个整数的顺序被视为同一种方法,例如 1999+3+181999+18+3 被视为同一种。
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一行,包含一个整数,表示满足条件的分解方法种数。
【样例输入】
2019
【样例输出】
40785
【评测用例规模与约定】
对于所有评测用例,100 ≤ n ≤ 2500
import java.util.Scanner;

public class B_TheNumberOfDecomposition 

	private static boolean judge(int s) 
		while( s > 0) 
			
			int t = s % 10;
			if(t== 2 || t== 4)
				return false;
			s /= 10;	
		
		return true;
	
	
	public static void main(String[] args) 
		
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int sum = 0;
		
		if(n >= 100 && n <= 2500)
			for (int i = 1; i <= n / 3 ; i++) 
				for (int j = 1; j < n; j++) 
					int k = n - i - j;
					if(k > j && i < j) 
						if (judge(i) && judge(j) && judge(k))
							sum ++;
					
				
				
		
		System.out.println(sum);		
	

3.“斐波那契”

 
 斐波那契
时间限制: 1.0s   内存限制: 512.0MB
【问题描述】
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
<此题禁止使用数组容器等数据结构>
 
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一行,包含一个整数,表示满足条件的数的和。
【样例输入】
22
【样例输出】
7704
【评测用例规模与约定】
对于所有评测用例,1 ≤ n ≤ 1,000,000
import java.util.Scanner;

public class C_FibonacciNumber 

	public static void main(String[] args) 
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
			long a  =1;
			long b = 1;
			long t = 1;
			for (long i = 2; i < n; i++) 
				t = a;
				a += b;
				a %= 10007;
				b = t;
			
			long result = a;
			System.out.println(result);	
	

Step2:JavaAPI(排序,容器,字符串,大数)

1.“日志统计”

      日志统计
时间限制: 1.0s   内存限制: 512.0MB
【问题描述】
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:
ts id 
表示在ts时刻编号id的帖子收到一个"赞"。 
 
现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。 
具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。 
 
给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。 
【输入格式】
第一行包含三个整数N、D和K。 
以下N行每行一条日志,包含两个整数ts和id。 
 
对于50%的数据,1 <= K <= N <= 1000 
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000 
 
【输出格式】
按从小到大的顺序输出热帖id。每个id一行。 
 
【输入样例】
7 10 2 
0 1 
0 10   
10 10 
10 1 
9 1
100 3 
100 3 
 
【输出样例】
1 
3 
package 精选思维15;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;

public class 日志统计step2 

	public static void main(String[] args) 
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int D = sc.nextInt();
		int K = sc.nextInt();
		
		int arr[][] = new int [N][5];
		for (int i = 0; i < N; i++) 
			arr[i][0] = sc.nextInt();
			arr[i][1] = sc.nextInt();
			
		
		for (int i = 0; i < N; i++) 
			int first =1;
			for (int j = i+1; j < N; j++) 
				if (arr[j][1]==arr[i][1]) 
					first++;
					if (j==N-1) 
						arr[i][2]=first;
			
		
		for (int i = 0; i < N; i++) 
			if (arr[i][2]>=K)
				arr[i][3]=1;
		
		
		for (int i = 0; i < N; i++) 
			for (int j = i+1; j < N; j++) 
				if (arr[i][3]==1&&arr[i][1]==arr[j][1]&&arr[j][0]-arr[i][0]<D) 
					arr[i][4]=1;
			
		
		HashSet<Integer> ar= new HashSet<Integer>(); 
		for (int i = 0; i < N; i++) 
			if (arr[i][4]==1) 
				ar.add(arr[i][1]);
			
		
		
		Iterator<Integer> result = ar.iterator();
		while (result.hasNext()) 
      
			System.out.println(result.next());
			
	

2.“复数幂”

复数幂
【问题描述】
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)123456次幂,这个数字很大,要求精确表示。
 
答案写成 "实部±虚部i" 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。
(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i
 
 
注意:需要提交的是一个很庞大的复数,不要填写任何多余内容。
package 精选思维15;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;

public class 复数幂step2 

	public static void main(String[] args) throws IOException 
		// TODO Auto-generated method stub
		int mi = 123456;
		BigInteger a = new BigInteger("2");
		BigInteger b = new BigInteger("3");
		BigInteger bigA;
		BigInteger bigB;
		
		for (int i = 0; i < mi-1; i++) 
			bigA =a.multiply(BigInteger.valueOf(2)).subtract(b.multiply(BigInteger.valueOf(3)));
			bigB =a.multiply(BigInteger.valueOf(3)).add(b.multiply(BigInteger.valueOf(2)));
			a = bigA;
			b = bigB;
		
		 
		FileWriter writer = new FileWriter("第十一届蓝桥/精选思维15题/bi.text");	
		writer.write(b.compareTo(BigInteger.ZERO) == 1 ? a + "+" + b + "i" : a + "" + b + "i");
		writer.flush();
	

3.“人物相关性分析”

   人物相关性分析
时间限制: 1.0s   内存限制: 512.0MB
【问题描述】
小明正在分析一本小说中的人物相关性。他想知道在小说中 Alice 和 Bob
有多少次同时出现。
更准确的说,小明定义 Alice 和 Bob“同时出现”的意思是:在小说文本
中 Alice 和 Bob 之间不超过 K 个字符。
例如以下文本:
This is a story about Alice and Bob. Alice wants to send a private message to Bob.
假设 K = 20,则 Alice 和 Bob 同时出现了 2 次,分别是”Alice and Bob”
和”Bob. Alice”。前者 Alice 和 Bob 之间有 5 个字符,后者有 2 个字符。
注意:
1. Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。
2. Alice 和 Bob 应为单独的单词,前后可以有标点符号和空格,但是不能
有字母。例如 Bobbi 並不算出现了 Bob。
【输入格式】
第一行包含一个整数 K。
第二行包含一行字符串,只包含大小写字母、标点符号和空格。长度不超
过 1000000。
【输出格式】
输出一个整数,表示 Alice 和 Bob 同时出现的次数。
【样例输入】
20
This is a story about Alice and Bob. Alice wants to send a private message to Bob.
【样例输出】
2
【评测用例规模与约定】
对于所有评测用例,1 ≤ K ≤ 1000000
import java.util.Scanner;

public class F_TheCharacterCorrelationAnalysis 

	public static void main(String[] args) 
		
		Scanner sc = new Scanner(System.in);
		int K = sc.nextInt();
		int num = 0;
		sc.nextLine();
		String paragraph = sc.nextLine();
		
		String[] stringList ;
		stringList = paragraph.split(" ");	
		
		for (int i = 0; i < stringList.length - 1; i++) 
			int length = 0;
			if(stringList[i].equals("Alice"))
				for (int j = i + 1; j < stringList.length; j++) 
					length += 1 + stringList[j].length();
					if(length <= K + 3 && stringList[j].equals("Bob")) 
						num ++;
						break;
					
					else if (length <= K + 4 && stringList[j].equals("Bob.")) 
						num ++;
						break;
					
					else if(length > K)
						break;	
				
			
			
			else if(stringList[i].以上是关于PostgreSQL最后的救命稻草 — pg_resetwal的主要内容,如果未能解决你的问题,请参考以下文章

Linux救命稻草--救援模式和单用户模式!

Linux救命稻草--救援模式和单用户模式!

018_线上救命稻草的几种重要方式

滴滴小巴上线:无奈的妥协还是真救命稻草

Oracle数据库冷备份与恢复(救命稻草)

自动驾驶,出行服务公司实现盈利的“救命稻草”?