PostgreSQL控制文件恢复

Posted 青空如璃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL控制文件恢复相关的知识,希望对你有一定的参考价值。

关于控制文件方面

Oracle:

1.控制文件是oracle数据库最重要的物理文件之一。每个oracle 数据库都必须至少有一个控制文件。在启动数据库实例时,oracle会根据初始化参数找到控制文件,并读取控制文件中的内容。然后根据控制文件中的信息(如数据库名称、数据文件和日志文件的名称和位置等)在实例和数据库之间建立起连接。
2.控制文件是一个二进制文件,它记录了数据库的物理结构,其中主要包括数据库名、数据文件、日志文件的名字和位置。
当oracle实例在正常启动时,系统首先要访问的是初始化参数文件spfile,然后oracle为系统全局区(SGA)分配内存,。这时oralce实例处于安装状态,并且控制文件处于打开状态,接下来oracle会自动读取出控制文件的所有数据文件和日志文件信息,并打开所有数据库中的所有数据文件和所有的日志文件以供用户访问。
oracle提供了备份文件和多路复用的机制。oracle数据库的控制文件是在创建数据库时自动创建的,一般情况下,至少需要一个副本。
 
同理PostgreSQL控制文件原理一样,只不过PG控制文件不像Oracle那样冗余、安全。
 
如果无法找到控制文件或控制文件损坏,则数据库实例将无法启动,并且很难修复。
 
(1)PG控制文件位置:

[postgres@pgccc01 bin]$ ls -la $PGDATA/global/pg_control
-rw-------. 1 postgres postgres 8192 Jun 9 10:50 /data/pg_data/global/pg_control

存储在pg_global表空间中,我们知道PG默认有两个表空间,一个是 pg_global,另一个是pg_default表空间,我们会在initdb初始化时形成。

 

postgres=# select * from pg_tablespace ;
oid | spcname | spcowner | spcacl | spcoptions
-------+--------------------+----------+-------------------+------------
1663 | pg_default | 10 | |
1664 | pg_global | 10 | |
16456 | tablespace_andyxi2 | 10 | |                   ##后面创建的表空间
16431 | tablespace_andyxi | 16389 | andyxi=C/andyxi |     ##后面创建的表空间
(4 rows)

(2)查看pg_controldata文件的内容

  有两种方式,

一种是通过SQL查询,如下:

select * from pg_catalog.pg_control_checkpoint();

select * from pg_catalog.pg_control_system();
select * from pg_catalog.pg_control_init(); -- 获取结果和pg_controldata相同
select * from pg_catalog.pg_control_recovery();

另一种是:

 

[postgres@pgccc01 bin]$ pg_controldata
pg_control version number: 1300
Catalog version number: 202209061
Database system identifier: 7238474806429805345
Database cluster state: in production
pg_control last modified: Fri 09 Jun 2023 10:50:42 AM CST
Latest checkpoint location: 0/10442160
Latest checkpoint\'s REDO location: 0/10442128
Latest checkpoint\'s REDO WAL file: 000000010000000000000010
Latest checkpoint\'s TimeLineID: 1
Latest checkpoint\'s PrevTimeLineID: 1
Latest checkpoint\'s full_page_writes: on
Latest checkpoint\'s NextXID: 0:810
Latest checkpoint\'s NextOID: 16471
Latest checkpoint\'s NextMultiXactId: 1
Latest checkpoint\'s NextMultiOffset: 0
Latest checkpoint\'s oldestXID: 717
Latest checkpoint\'s oldestXID\'s DB: 5
Latest checkpoint\'s oldestActiveXID: 810
Latest checkpoint\'s oldestMultiXid: 1
Latest checkpoint\'s oldestMulti\'s DB: 16392
Latest checkpoint\'s oldestCommitTsXid:0
Latest checkpoint\'s newestCommitTsXid:0
Time of latest checkpoint: Fri 09 Jun 2023 10:49:11 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: 86f315bd65a4f0a2eb33d3001509754570cfcef6f0858c1bf2759b1612615131

(3)我们现在模拟pg_control这个控制文件损坏,进一步分析和恢复

我们在做实验之前,来了解一下重建控制命令(PostgreSQL10版本以后):

[postgres@pgccc01 pg_wal]$ 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

Report bugs to <pgsql-bugs@lists.postgresql.org>.
PostgreSQL home page: <https://www.postgresql.org/>

同时,我们先了解下数据库目录文件有哪些:

[postgres@pgccc01 pg_data]$ ls -la
total 68
drwx------. 20 postgres postgres 4096 Jun 9 10:14 .
drwxr-xr-x. 9 postgres postgres 269 Jun 7 15:36 ..
drwx------. 7 postgres postgres 63 May 30 13:39 base
drwx------. 2 postgres postgres 4096 Jun 9 10:14 global
drwx------. 2 postgres postgres 6 May 29 13:39 pg_commit_ts
drwx------. 2 postgres postgres 6 May 29 13:39 pg_dynshmem
-rw-------. 1 postgres postgres 4789 May 29 13:39 pg_hba.conf
-rw-------. 1 postgres postgres 1636 Jun 8 15:39 pg_ident.conf
drwx------. 4 postgres postgres 68 Jun 9 10:49 pg_logical
drwx------. 4 postgres postgres 36 May 29 13:39 pg_multixact
drwx------. 2 postgres postgres 6 May 29 13:39 pg_notify
drwx------. 2 postgres postgres 6 May 29 13:39 pg_replslot
drwx------. 2 postgres postgres 6 May 29 13:39 pg_serial
drwx------. 2 postgres postgres 6 May 29 13:39 pg_snapshots
drwx------. 2 postgres postgres 6 Jun 9 10:14 pg_stat
drwx------. 2 postgres postgres 6 May 29 13:39 pg_stat_tmp
drwx------. 2 postgres postgres 18 May 29 13:39 pg_subtrans
drwx------. 2 postgres postgres 32 Jun 7 15:37 pg_tblspc
drwx------. 2 postgres postgres 6 May 29 13:39 pg_twophase
-rw-------. 1 postgres postgres 3 May 29 13:39 PG_VERSION
drwx------. 3 postgres postgres 92 Jun 9 10:50 pg_wal
drwx------. 2 postgres postgres 18 May 29 13:39 pg_xact
-rw-------. 1 postgres postgres 88 Jun 7 09:25 postgresql.auto.conf
-rw-------. 1 postgres postgres 29804 Jun 2 13:26 postgresql.conf
-rw-------. 1 postgres postgres 27 Jun 9 10:14 postmaster.opts
-rw-------. 1 postgres postgres 71 Jun 9 10:14 postmaster.pid
drwxrwxr-x. 3 postgres postgres 29 May 30 13:51 tablespace_andyxi

我们恢复控制文件,需要先了解一下这几个数据库目录文件

[postgres@pgccc01 pg_data]$ ls -la pg_xact/
total 12
drwx------. 2 postgres postgres 18 May 29 13:39 .
drwx------. 20 postgres postgres 4096 Jun 9 10:14 ..
-rw-------. 1 postgres postgres 8192 Jun 9 10:49 0000
[postgres@pgccc01 pg_data]$ ls -la pg_wal/
total 32772
drwx------. 3 postgres postgres 92 Jun 9 10:50 .
drwx------. 20 postgres postgres 4096 Jun 9 10:14 ..
-rw-------. 1 postgres postgres 16777216 Jun 9 10:50 000000010000000000000010
-rw-------. 1 postgres postgres 16777216 Jun 9 10:48 000000010000000000000011
drwx------. 2 postgres postgres 6 Jun 2 13:31 archive_status
[postgres@pgccc01 pg_data]$ ls -la pg_multixact/
total 4
drwx------. 4 postgres postgres 36 May 29 13:39 .
drwx------. 20 postgres postgres 4096 Jun 9 10:14 ..
drwx------. 2 postgres postgres 18 May 29 13:39 members
drwx------. 2 postgres postgres 18 May 29 13:39 offsets
[postgres@pgccc01 pg_data]$ ls -la pg_multixact/members/
total 8
drwx------. 2 postgres postgres 18 May 29 13:39 .
drwx------. 4 postgres postgres 36 May 29 13:39 ..
-rw-------. 1 postgres postgres 8192 May 29 13:39 0000
[postgres@pgccc01 pg_data]$ ls -la pg_multixact/offsets/
total 8
drwx------. 2 postgres postgres 18 May 29 13:39 .
drwx------. 4 postgres postgres 36 May 29 13:39 ..
-rw-------. 1 postgres postgres 8192 Jun 9 10:19 0000

 控制文件的恢复涉及到16进制的转换问题,如:

 

模拟pg_control不存在

 PostgreSQL不能启动

 

 

pg_resetwal最关键的步骤:

1.参数-l

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

通过指定下一个WAL段文件名称来手工设置WAL开始位置

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

进入pg_wal(相当于redo log)

[postgres@pgccc01 pg_data]$ cd /data/pg_data/pg_wal/
[postgres@pgccc01 pg_wal]$ ls -la
total 32772
drwx------. 3 postgres postgres 92 Jun 9 10:50 .
drwx------. 20 postgres postgres 4096 Jun 9 13:31 ..
-rw-------. 1 postgres postgres 16777216 Jun 9 13:29 000000010000000000000010
-rw-------. 1 postgres postgres 16777216 Jun 9 10:48 000000010000000000000011
drwx------. 2 postgres postgres 6 Jun 2 13:31 archive_status

此时最新文件是000000010000000000000011 需要编号+1,000000010000000000000012(16进制)

2.参数-O

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

 

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

 

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

 

上述pg_multixact日志0000文件最大值为0,一般这个数不变

取最大值加1,然后乘以65536,再转换成16进制为10000,然后末尾添加5个0

 -O=0x1000000000

3.参数-m

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

 

手工设置下一个和最老的多事务 ID。

 

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

 

日志0000文件最大值为0,一般这个数不变,取最大值编号后加1,然后末尾添加4个0

-m=0x00010000,0x00010000

 

4 参数-x

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

手工设置下一个事务 ID。

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

 j最大文件编码取最大值加1,然后末尾添加5个0

-x=0x000100000

 

在global表空间创建pg_control空文件

 

最后用pg_resetwal命令加上相应参数进行恢复

pg_resetwal -l 000000010000000000000012  -O 0x1000000000  -m 0x00010000,0x00010000 -x 0x000100000 -f $PGDATA

这个命令不能在服务器正在运行时被使用。如果在数据目录中发现一个服务器锁文件,pg_resetwal将拒绝启动。如果服务器崩溃那么一个锁文件可能会被留下,在那种情况下你能移除该锁文件来让pg_resetwal运行。但是在你那样做之前,再次确认没有服务器进程仍然存活。

 删除postmaster.pid后,显示

 这时pg_control回来了

 pg_controldata也可以运行了

[postgres@pgccc01 pg_data]$ pg_controldata

PostgreSQL启动正常:

 

postgresql学习笔记备份与恢复

postgresql学习笔记(五)备份与恢复

1、备份工具:pg_dump和pg_dumpall

pg_dump可备份一个指定的database

pg_dumpall可一次性备份所有database的数据及系统全局数据

2、pg_dump和pg_dumpall工具不支持在命令行选项中设定登录密码,因此为了便于执行自动任务,你需要在postgres操作系统帐号的home文件夹下创建一个密码文件.pgpass来存储密码;或者也可以用PGPASSWORD环境变量来设定密码。

3、如果你希望每天都进行备份,那么使用pg_dump比pg_dumpall更合适,因为前者支持精确指定要备份的表,schema和database,而后者不支持。

4、pg_dump可以将数据备份为SQL文本文件格式,也支持备份为用户定义压缩格式或者是TAR包格式,在数据恢复时,对压缩格式和TAR包格式的备份文件可以实现并行恢复,该特性是从8.4版开始支持的。

5、pg_dumpall工具可以将当前postgresql服务实例中所有database的数据都导出为SQL文本(pg_dumpall不支持导出SQL文本以外的其他格式),也可以同时导出表间定义和角色等全局对象。

6、pg_dump用法:

(1)备份某个database,备份结果以自定压缩格式输出 :

pg_dump -h 127.0.0.1 -p 5432 -U postgres -F c -b -v -f test.backup test

(2)备份某个database,备份结果以SQL文本方式输出,输出结果中需包括CREATE DATABASE语句;

pg_dump -h 127.0.0.1 -p 5432 -U postgres -C -F p -b -v -f test.sql test

(3)备份某个database中所有名称以“pay”开头的表,备份结果以自定义压缩格式输出:

pg_dump -h 127.0.0.1 -p 5432 -U postgres -F c -b -v -t *.pay* -f pay.backup test

(4)备份某个database中hr和payroll这两个schema中的所有数据,备份结果以自定义压缩格式输出:

pg_dump -h 127.0.0.1 -p 5432 -U postgres -F c -b -v -n hr -n payroll -f hr.backup mydb

(5)备份某个database中除了public schema中的数据以外的所有数据,备份结果以自定义压缩格式输出:

pg_dump -h 127.0.0.1 -p 5432  -U postgres -F c -b -v -N public -f all_sch_except_pub.backup mydb

(6)将数据备份为SQL文本文件,且生成的INSERT语句是带有字段名列表的标准格式,该文件可用于将数据导入到低于当前版本的PostgreSQL或者其他支持SQL的非PostgreSQL数据库中。

pg_dump -h 127.0.0.1 -p 5432  -U postgres -F p --column-inserts -f select_tables.backup mydb

(7)目录格式备份,解决了以其他备份格式时可能存在的单个文件大小超出操作系统限制的问题

pg_dump -h 127.0.0.1 -p 5432  -U postgres -F d -f /somepath/a_directory mydb

(8)目录格式并行备份

pg_dump -h 127.0.0.1 -p 5432  -U postgres -j 3 -Fd -f /somepath/a_directory mydb

7、pg_dumpall 建议每天都对角色和表空间定义等全局对象进行备份,但不建议每天都使用pg_dumpall来备份全库数据,因为pg_dumpall仅支持导出为SQL文本格式,而使用这种庞大的SQL文本备份来进行全库级别

的数据恢复是极其耗时的,所以一般只建议用pg_dumpall来备份全局对象而非全库数据,如果你一定要用pg_dumpall来备份全库数据的话,一般一个月执行一次就够了。

(1)仅备份角色和表空间定义

pg_dumpall -h localhost -U postgres --port=5432 -f myglobals.sql --globals-only

 (2)仅需备份角色定义而无需备份表空间,那么可以加上--roles-only选项

pg_dumpall -h localhost -U postgres --port=5432 -f myglobals.sql --roles-only

8、数据恢复方法

(1)使用psql来恢复pg_dump或者pg_dumpall工具生成的SQL文本格式的数据备份;

(2)使用pg_restore工具来恢复由pg_dump工具生成的自定义压缩格式,TAR包格式或者目录格式备份

9、使用psql恢复SQL文本格式的数据备份

 (1)恢复一个SQL备份文件并忽略过程中可能发生的所有错误

psql -U postgres -f myglobals.sql

(2)恢复一个SQL备份文件,如遇任何错误则立好停止恢复

psql -U postgres --set ON_ERROR_STOP=on -f myglobals.sql

(3)将SQL文本中的数据恢复到某个指定的database:

psql -U postgres -d mydb -f select_objects.sql


10、使用pg_restore进行恢复

(1)在使用pg_restore执行恢复动作之前,请创建目标数据库

create database mydb;

 执行恢复:

pg_restore --dbname=mydb --jobs=4 --verbose mydb.backup

 (2)如果备份和恢复时使用的database同名,则可以通过加--create选项省去单独建库的过程

pg_restore --dbname=postgres --create --jobs=4 --verbose mydb.backup

 (3)恢复表结构而不恢复表数据

create database mydb2;
pg_resotre --dbname=mydb2 --section=pre-data --jobs=4 mydb.backup


本文出自 “corasql” 博客,请务必保留此出处http://corasql.blog.51cto.com/5908329/1920949

以上是关于PostgreSQL控制文件恢复的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL启动恢复通过checkpoint open wal文件

postgresql使用pg_basebackup备份与恢复

postgresql学习笔记备份与恢复

PostgreSQL 时间点恢复不起作用

pg_restore - 从一个由 pg_dump 创建的备份文件中恢复 PostgreSQL 数据库。

postgresql备份与恢复数据库