When running a PostgreSQL database system how do I know my database as a whole has 100% integrity? Basically how do I know if my data files and pages are all 100% good with no corruption?
In the Microsoft SQL Server world there’s a command that you can execute DBCC CHECKDB that will tell you if there’re issues. Here’s a link if your intrested in learning more on the command. DBCC CHECKDB (Transact-SQL)
I’m a paranoid database integrity minded person (which anyone who works with the database in a DBA type role should be) and this type of stuff makes it hard for me to sleep well at night. A utility like this is a must! Searches on google have found a few attempts at tools like this and in my opinion unless it’s an official accepted tool by the PostgreSQL project I won’t trust it for something this important.
Here are some links to people asking similar questions with what I consider no real definitive answer. And in my opinion shows that PostgreSQL needs to have some tools in place that Oracle and Microsoft SQL Server seem to have.
The first link is the most interesting I have found on this subject. I think a comment on the article that probably sums it up states: «Postgres is pretty lame when it comes to identifying database corruption and repairing it. The only way to detect it is by dumping the database or select * from every table in the database.»
How PostgreSQL protects against partial page writes and data corruption
Checking data and index file corruption — Dev Shed
Help: my table is corrupt!
PostgreSQL: Corrupt primary key, inconsistent table
I believe there is a chance 9.3 might have some corruption checking features. It appears there may be hope to having page files check summed if one chooses. So things are looking bright if you consider using ZFS and/or a future version of Postgres with page check summing.
https://commitfest.postgresql.org/action/patch_view?id=759
UPDATE: 14-JAN-2012 — Seems like using a file system based on ZFS can detect corruption by check summing each block of data. I will have to look into this further and see if this is a work around to allow one to sleep well at night knowing their database data is not silently going corrupt.
UPDATE: 17-JAN-2012 — How to find what files are corrupt with ZFS. http://docs.oracle.com/cd/E18752_01/html/819-5461/gbbwl.html#gbcuz
UPDATE:14-APR-2014 9.3 did get data checksums. https://wiki.postgresql.org/wiki/What’s_new_in_PostgreSQL_9.3
When running a PostgreSQL database system how do I know my database as a whole has 100% integrity? Basically how do I know if my data files and pages are all 100% good with no corruption?
In the Microsoft SQL Server world there’s a command that you can execute DBCC CHECKDB that will tell you if there’re issues. Here’s a link if your intrested in learning more on the command. DBCC CHECKDB (Transact-SQL)
I’m a paranoid database integrity minded person (which anyone who works with the database in a DBA type role should be) and this type of stuff makes it hard for me to sleep well at night. A utility like this is a must! Searches on google have found a few attempts at tools like this and in my opinion unless it’s an official accepted tool by the PostgreSQL project I won’t trust it for something this important.
Here are some links to people asking similar questions with what I consider no real definitive answer. And in my opinion shows that PostgreSQL needs to have some tools in place that Oracle and Microsoft SQL Server seem to have.
The first link is the most interesting I have found on this subject. I think a comment on the article that probably sums it up states: «Postgres is pretty lame when it comes to identifying database corruption and repairing it. The only way to detect it is by dumping the database or select * from every table in the database.»
How PostgreSQL protects against partial page writes and data corruption
Checking data and index file corruption — Dev Shed
Help: my table is corrupt!
PostgreSQL: Corrupt primary key, inconsistent table
I believe there is a chance 9.3 might have some corruption checking features. It appears there may be hope to having page files check summed if one chooses. So things are looking bright if you consider using ZFS and/or a future version of Postgres with page check summing.
https://commitfest.postgresql.org/action/patch_view?id=759
UPDATE: 14-JAN-2012 — Seems like using a file system based on ZFS can detect corruption by check summing each block of data. I will have to look into this further and see if this is a work around to allow one to sleep well at night knowing their database data is not silently going corrupt.
UPDATE: 17-JAN-2012 — How to find what files are corrupt with ZFS. http://docs.oracle.com/cd/E18752_01/html/819-5461/gbbwl.html#gbcuz
UPDATE:14-APR-2014 9.3 did get data checksums. https://wiki.postgresql.org/wiki/What’s_new_in_PostgreSQL_9.3
Asked
12 years, 5 months ago
Viewed
28k times
Is there a way to check PostgreSQL database(s) integrity and consistency? I know about SQL Server DBCC CHECKDB and wonder if there is something similar to PostgreSQL.
asked Aug 29, 2010 at 15:46
2
In 12 version of pgsql, there is pg_checksums.
answered Nov 26, 2019 at 13:16
![]()
What do you really want to achieve?
The database itself guarantees its integrity. You do not need tools to fiddle with.
answered Aug 29, 2010 at 18:08
cstamascstamas
6,64724 silver badges42 bronze badges
4
answered Aug 29, 2010 at 20:26
![]()
alerootaleroot
3,1705 gold badges28 silver badges37 bronze badges
2
Оглавление
- 1 Параметры
- 1.1 Databases
- 1.2 CheckCommands
- 1.3 PhysicalOnly
- 1.4 NoIndex
- 1.5 ExtendedLogicalChecks
- 1.6 TabLock
- 1.7 FileGroups
- 1.8 Objects
- 1.9 MaxDOP
- 1.10 AvailabilityGroups
- 1.11 AvailabilityGroupReplicas
- 1.12 Updateability
- 1.13 LockTimeout
- 1.14 LogToTable
- 1.15 Execute
- 2 Примеры использования вложенной процедуры
-
- 2.0.1 A. Проверка целостности во всех пользовательских базах
- 2.0.2 B. Проверка физической целостности данных во всех пользовательских базах
- 2.0.3 C. Проверка целостности данных во всех пользовательских базах, с использованием опции исключающей проверку не кластеризованных индексов
- 2.0.4 D. Проверка целостности данных во всех пользовательских базах, с использованием опции упрощенной проверки логической структуры
- 2.0.5 E. Проверка целостности данных в файловой группе PRIMARY базы данных AdventureWorks
- 2.0.6 F. Проверка целостности данных во всех файловых группах, за исключением файловой группы PRIMARY базы данных AdventureWorks
- 2.0.7 G. Проверка целостности данных в таблице Production.Product базы данных AdventureWorks
- 2.0.8 H. Проверка целостности данных всех таблиц за исключение таблицы Production.Product базы данных AdventureWorks
- 2.0.9 I. Проверка дискового места во всех пользовательских базах
-
- 3 Выполнение
Процедура от Ola Hallengren — DatabaseIntegrityCheck, позволяет проверить базу, файловую группу или таблицу. Если используется полноценный SQL Server, то можно использовать его в Maintains Paln. Если SQL Express, то можно использовать данную процедуру в планировщике, так как агент-SQL в этой редакции отсутствует. Проверка необходима перед архивацией базы. Нет смысла архивировать разрушенную базу!!! поэтому перед архивацией необходим проверить целостность данных. В качестве параметров можно указать список баз данных, время блокировки, объекты проверки и некоторые другие параметры. Данную процедуру удобно использовать при большом количестве баз данных или при обслуживании баз разработчиков, которые постоянно плодят новые ветки и заливают в новые базы. Полный список параметров и примеры использования ниже
Параметры
В качестве аргументов, отвечающих за выбор объектов проверки можно передать SYSTEM_DATABASES, USER_DATABASES, ALL_DATABASES и AVAILABILITY_GROUP_DATABASES, если поддерживается. Знак (-) используется для исключения базы, а знак процента (%) выполняет роль символа подстановки. Все используемые параметры могут быть разделены занятой (,)
Databases
| Переменная | Описание |
|---|---|
| SYSTEM_DATABASES | Все системные базы (master, msdb, and model) |
| USER_DATABASES | Все пользовательские базы |
| ALL_DATABASES | Все базы |
| AVAILABILITY_GROUP_DATABASES | Все базы и группы доступности |
| USER_DATABASES, -AVAILABILITY_GROUP_DATABASES | Все пользовательские базы, исключая группы доступности |
| Db1 | Ваза Db1 |
| Db1, Db2 | Базы Db1 и Db2 |
| USER_DATABASES, -Db1 | Все пользовательские базы, за исключением Db1 |
| %Db% | Все базы, имеющие в названии Db |
| %Db%, -Db1 | Все базы имеющие в названии Db, за исключением базы Db1 |
| ALL_DATABASES, -%Db% | Все базы, за исключением тех, которые имеют в названии Db |
CheckCommands
Использование данного параметра может ускорить скорость проверки путем исключения не нужных объектов или разделить задание на два этапа.
| Переменная | Описание |
|---|---|
| CHECKDB | Проверяет логическую и физическую целостность всех объектов. По умолчанию |
| CHECKFILEGROUP | Проверяет распределение и структуру целостности всех таблиц и индексированных представлений в файловой группе |
| CHECKTABLE | Проверяет целостность всех страниц и структур, составляющих таблицу или индексированное представление |
| CHECKALLOC | Проверяет согласованность структур выделения места на диске |
| CHECKCATALOG | Проверяет согласованность каталогов в указанной базе данных |
| CHECKALLOC,CHECKCATALOG | Совмещает два параметра — проверку таблиц и представлений |
| CHECKFILEGROUP,CHECKCATALOG | Проверяет представления и таблицы для файловых групп |
| CHECKALLOC,CHECKTABLE,CHECKCATALOG | Проверяет параметры свободного места для таблиц и индексов, а также согласованность каталогов |
При составлении команд использовалось описание для SQL Server: DBCC CHECKDB проверка баз данных, DBCC CHECKFILEGROUP проверка фаловых групп, DBCC CHECKTABLE проверка таблиц и индексных представлений, DBCC CHECKALLOC проверка свободного места в таблицах и DBCC CHECKCATALOG проверка согласованности каталогов.
PhysicalOnly
Ограничиться только физической проверкой структуры базы
| Переменная | Описание |
|---|---|
| Y | Ограничиться только физической проверкой структуры базы |
| N | Не ограничиться только физической проверкой структуры базы. По умолчанию |
Параметр PHYSICAL_ONLY использует опции следующих команд DBCC CHECKDB, DBCC CHECKFILEGROUP и DBCC CHECKTABLE
NoIndex
Не проверять не кластеризированные индексы
| Переменная | Описание |
|---|---|
| Y | Не проверять |
| N | Проверять. По умолчанию |
Параметр NoIndex использует опции следующих команд DBCC CHECKDB, DBCC CHECKFILEGROUP, DBCC CHECKTABLE и DBCC CHECKALLOC
ExtendedLogicalChecks
Упрощенная проверка логической структуры
| Переменная | Описание |
|---|---|
| Y | Провести простую проверку |
| N | Не проводить простую проверку. По умолчанию |
Параметр ExtendedLogicalChecks использует опции следующих команд EXTENDED_LOGICAL_CHECKS и команды SQL Server DBCC CHECKDB
Нельзя комбинировать параметры PhysicalOnly и ExtendedLogicalChecks.
TabLock
Позволяет использовать внешний снапшот
| Переменная | Описание |
|---|---|
| Y | Использовать блокировку, для проверки |
| N | Использовать снапшот. По умолчанию |
Параметр TabLock использует опции следующих команд DBCC CHECKDB, DBCC CHECKFILEGROUP, DBCC CHECKTABLE и DBCC CHECKALLOC
FileGroups
Выбор файловых групп. Данный параметр поддерживает выборку по словам. Знак минус (-) позволяет исключить файловую группу, а знак процента (%) позволяет задать маску. Все операторы могут быть объединены запятой (,)
| Переменная | Описание |
|---|---|
| ALL_FILEGROUPS | Все файловые группы |
| Db1.FileGroup1 | Файловая группа FileGroup1 в базе Db1 |
| Db1.FileGroup1, Db2.FileGroup2 | Файловая группа FileGroup1 в базе Db1 и фаловая группа FileGroup2 в базе Db2 |
| ALL_FILEGROUPS, -Db1.FileGroup1 | Все файловые группы, за исключением FileGroup1 в базе Db1 |
| Db1.%FileGroup% | Все файловые группы в базе Db1 имеющие в своем имени “FileGroup” |
Используются только специфические опции CHECKFILEGROUPS.
Objects
Выбор объектов. Параметр ALL_OBJECTS поддерживает выбор по маске. Знак минус (-) позволяет исключить файловую группу, а знак процента (%) позволяет задать маску. Все операторы могут быть объединены запятой (,)
| Переменная | Описание |
|---|---|
| ALL_OBJECTS | Все объекты |
| Db1.Schema1.Tbl1 | Объект Schema1.Tbl1 в базе Db1 |
| Db1.Schema1.Object1, Db2.Schema2.Object2 | Объект Schema1.Tbl1 в базе Db1 и объект Schema2.Tbl2 б базе данных Db2 |
| ALL_OBJECTS, -Db1.Schema1.Object1 | Все объекты, кроме Schema1.Object1 в базе Db1 |
| Db1.Schema1.% | Все объекты в схеме Schema1 находящейся в базе Db1 |
Данный параметр можно использовать только совместно с параметром CHECKTABLE
MaxDOP
Количество ядер процессора выделенных для проверки базы, файловой группы или таблицы. Если данный параметр не задан, будут использоваться максимальное значение степени параллелизма.
Данный параметр может быть использован совместно с параметрами DBCC CHECKDB, DBCC CHECKFILEGROUP и DBCC CHECKTABLE
AvailabilityGroups
выбор групп доступности. Параметр ALL_AVAILABILITY_GROUPS разрешает использование маски. Знак минус (-) позволяет исключить файловую группу, а знак процента (%) позволяет задать маску. Все операторы могут быть объединены запятой (,)
| Переменная | Описание |
|---|---|
| ALL_AVAILABILITY_GROUPS | Все группы доступности |
| AG1 | Группа доступности AG1 |
| AG1, AG2 | Группа доступности AG1 и AG1 |
| ALL_AVAILABILITY_GROUPS, -AG1 | Все группы доступности, за исключением группы AG1 |
| %AG% | Все группы доступности содержащие в своем имени “AG” |
| %AG%, -AG1 | Все группы доступности содержащие в своем имени “AG” за исключением группы AG1 |
| ALL_AVAILABILITY_GROUPS, -%AG% | Все группы доступности не содержащие в своем имени “AG” |
AvailabilityGroupReplicas
Выбор реплики для необходимости проверки.
| Переменная | Описание |
|---|---|
| ALL | Проверяжтся все реплики. По умолчанию |
| PRIMARY | Проверяется только первичная реплика |
| SECONDARY | Проверяется только вторичная реплика |
Updateability
Задает режим для базы данны READ_ONLY/READ_WRITE
| Переменная | Описание |
|---|---|
| ALL | READ_ONLY и READ_WRITE — база данных. До умолчанию |
| READ_ONLY | READ_ONLY — только чтение |
| READ_WRITE | READ_WRITE — чтение запись |
Переменная READ_ONLY в sys.databases используется если база в режиме READ_ONLY или READ_WRITE (Трудности перевода, пока не разбирался с данной переменной)
LockTimeout
Устанавливает время блокировки, после которого необходимо освободить захваченный объект. По умолчанию лимит отсутствует.
Параметр LockTimeout в хранимой процедуре IndexOptimize использует SET LOCK_TIMEOUT в терминологии SQL Server.
LogToTable
Логирование команд в таблицу dbo.CommandLog
| Переменная | Описание |
|---|---|
| Y | Логировать команды в таблицу |
| N | Не логировать команды. По умолчанию |
Execute
Выполнение команд. По умолчанию команды отправляются на выполнение. Если установлено значение N, то команды будут выведены без выполнения.
| Переменная | Описание |
|---|---|
| Y | Выполнять команды. По умолчанию |
| N | Только вывеси команды |
Примеры использования вложенной процедуры
A. Проверка целостности во всех пользовательских базах
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKDB’
B. Проверка физической целостности данных во всех пользовательских базах
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKDB’,
@PhysicalOnly = ‘Y’
C. Проверка целостности данных во всех пользовательских базах, с использованием опции исключающей проверку не кластеризованных индексов
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKDB’,
@NoIndex = ‘Y’
D. Проверка целостности данных во всех пользовательских базах, с использованием опции упрощенной проверки логической структуры
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKDB’,
@ExtendedLogicalChecks = ‘Y’
E. Проверка целостности данных в файловой группе PRIMARY базы данных AdventureWorks
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘AdventureWorks’,
@CheckCommands = ‘CHECKFILEGROUP’,
@FileGroups = ‘AdventureWorks.PRIMARY’
F. Проверка целостности данных во всех файловых группах, за исключением файловой группы PRIMARY базы данных AdventureWorks
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKFILEGROUP’,
@FileGroups = ‘ALL_FILEGROUPS, -AdventureWorks.PRIMARY’
G. Проверка целостности данных в таблице Production.Product базы данных AdventureWorks
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘AdventureWorks’,
@CheckCommands = ‘CHECKTABLE’,
@Objects = ‘AdventureWorks.Production.Product’
H. Проверка целостности данных всех таблиц за исключение таблицы Production.Product базы данных AdventureWorks
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKTABLE’,
@Objects = ‘ALL_OBJECTS, -AdventureWorks.Production.Product’
I. Проверка дискового места во всех пользовательских базах
EXECUTE dbo.DatabaseIntegrityCheck
@Databases = ‘USER_DATABASES’,
@CheckCommands = ‘CHECKALLOC’
Выполнение
Для выполнения хранимой процедуры, необходимо использовать sqlcmd и опцию -b. Вызов процедуры происходит по имени
|
sqlcmd —E —S $(ESCAPE_SQUOTE(SRVR)) —d master —Q «EXECUTE dbo.DatabaseIntegrityCheck @Databases = ‘USER_DATABASES'» —b |
Загрузка…
Media failure is one of the crucial things that the database administrator should be aware of. Media failure is nothing but a physical problem reading or writing to files on the storage medium.
A typical example of media failure is a disk head crash, which causes the loss of all files on a disk drive. All files associated with a database are vulnerable to a disk crash, including datafiles, wal files, and control files.
This is the comprehensive post which focuses on disk failure in PostgreSQL and the ways you can retrieve the data from PostgreSQL Database after failure(other than restoring the backup).
In this post, we are going to do archaeology on the below error and will understand how to solve the error.
WARNING: page verification failed, calculated checksum 21135 but expected 3252
ERROR: invalid page in block 0 of relation base/13455/16395
During the process, you are going to learn a whole new bunch of stuff in PostgreSQL.
PostgreSQL Checksum: The definitive guide
- Chapter 1: What is a checksum?
- Chapter 2: PostgreSQL checksum: Practical implementation
- Chapter 3: How to resolve the PostgreSQL corrupted page issue?
With v9.3, PostgreSQL introduced a feature known as data checksums and it has undergone many changes since then. Now we have a well-sophisticated view in PostgreSQL v12 to find the checksums called pg_checksums.
But what is a PostgreSQL checksum?
When the checksum is enabled, a small integer checksum is written to each “page” of data that Postgres stores on your hard drive. Upon reading that block, the checksum value is recomputed and compared to the stored one.
This detects data corruption, which (without checksums) could be silently lurking in your database for a long time.
Good, checksum, when enabled, detects data corruption.
How does PostgreSQL checksum work?
PostgreSQL maintains page validity primarily on the way in and out of its buffer cache.
Also read: A comprehensive guide – PostgreSQL Caching
From here we understood that the PostgreSQL page has to pass through OS Cache before it leaves or enters into shared buffers. So page validity happens before leaving the shared buffers and before entering the shared buffers.
when PostgreSQL tries to copy the page into its buffer cache then it will (if possible) detect that something is wrong, and it will not allow page to enter into shared buffers with this invalid 8k page, and error out any queries that require this page for processing with the ERROR message
ERROR: invalid page in block 0 of relation base/13455/16395
If you already have a block with invalid data at disk-level and its page version at buffer level, during the next checkpoint, while page out, it will update invalid checksum details but which is rarely possible in real-time environments.
confused, bear with me.
And finally,
If the invalid byte is part of the PostgreSQL database buffer cache, then PostgreSQL will quite happily assume nothing is wrong and attempt to process the data on the page. Results are unpredictable; Some times you will get an error and sometimes you may end up with wrong data.
How PostgreSQL Checks Page Validity?
In a typical page, if data checksums are enabled, information is stored in a 2-byte field containing flag bits after the page header.
Also Read: A comprehensive guide on PostgreSQL: page header
This is followed by three 2-byte integer fields (pd_lower, pd_upper, and pd_special). These contain byte offsets from the page start to the start of unallocated space, to the end of unallocated space, and to the start of the special space.
The checksum value typically begins with zero and every time reading that block, the checksum value is recomputed and compared to the stored one. This detects data corruption.
Checksums are not maintained for blocks while they are in the shared buffers – so if you look at a buffer in the PostgreSQL page cache with pageinspect and you see a checksum value, note that when you do page inspect on a page which is already in the buffer, you may not get the actual checksum. The checksum is calculated and stamped onto the page when the page is written out of the buffer cache into the operating system page cache.
Also read: A comprehensive guide – PostgreSQL Caching
Let’s work on the practical understanding of whatever we learned so far.
I have a table check_corruption wherein I am going to do all the garbage work.
- my table size is 8 kB.
- has 5 records.
- the version I am using is PostgreSQL v12.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
postgres=# select * from check_corruption; aid | bid | abalance | filler ———+———+—————+——————————————————————————————————————————— 1 | 1 | 0 | This is checksum example, checksum is for computing block corruption 2 | 1 | 0 | This is checksum example, checksum is for computing block corruption 3 | 1 | 0 | This is checksum example, checksum is for computing block corruption 4 | 1 | 0 | This is checksum example, checksum is for computing block corruption 5 | 1 | 0 | This is checksum example, checksum is for computing block corruption (5 rows) postgres=# SELECT * FROM page_header(get_raw_page(‘check_corruption’,0)); lsn | checksum | flags | lower | upper | special | pagesize | version | prune_xid ——————+—————+————+————+————+—————+—————+—————+—————— 0/17EFCA0 | 0 | 0 | 44 | 7552 | 8192 | 8192 | 4 | 0 (1 row) postgres=# dt+ check_corruption List of relations Schema | Name | Type | Owner | Size | Description ————+—————————+————+—————+——————+——————— public | check_corruption | table | postgres | 8192 bytes | (1 row) postgres=# select pg_relation_filepath(‘check_corruption’); pg_relation_filepath ——————————— base/13455/16490 (1 row) postgres=# |
First, check whether the checksum is enabled or not?
[postgres@stagdb ~]$ pg_controldata -D /u01/pgsql/data | grep checksum
Data page checksum version: 0
[postgres@stagdb ~]$
It is disabled.
Let me enable the page checksum in PostgreSQL v12.
Syntax: pg_checksums -D /u01/pgsql/data –enable –progress –verbose
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[postgres@stagdb ~]$ pg_checksums —D /u01/pgsql/data —enable —progress —verbose pg_checksums: checksums enabled in file «/u01/pgsql/data/global/2847» pg_checksums: checksums enabled in file «/u01/pgsql/data/global/1260_fsm» pg_checksums: checksums enabled in file «/u01/pgsql/data/global/4175» .. .. 23/23 MB (100%) computed Checksum operation completed Files scanned: 969 Blocks scanned: 3006 pg_checksums: syncing data directory pg_checksums: updating control file Data checksum version: 1 Checksums enabled in cluster |
Again, check the status of checksums in PostgreSQL
[postgres@stagdb ~]$
[postgres@stagdb ~]$ pg_controldata -D /u01/pgsql/data | grep checksum
Data page checksum version: 1
[postgres@stagdb ~]$
we can disable the checksums with –disable option
|
[postgres@stagdb ~]$ [postgres@stagdb ~]$ pg_checksums —D /u01/pgsql/data —disable pg_checksums: syncing data directory pg_checksums: updating control file Checksums disabled in cluster [postgres@stagdb ~]$ |
Let’s first check the current data directory for errors, then play with data.
To check the PostgreSQL page errors, we use the following command.
pg_checksums -D /u01/pgsql/data –check
[postgres@stagdb ~]$ pg_checksums -D /u01/pgsql/data –check
Checksum operation completed
Files scanned: 969
Blocks scanned: 3006
Bad checksums: 0
Data checksum version: 1
[postgres@stagdb ~]$
Warning!! Do not perform the below case study in your production machine.
As the table check_corruption data file is 16490, I am going to corrupt the file with the Operating system’s dd command.
dd bs=8192 count=1 seek=1 of=16490 if=16490
[postgres@stagdb 13455]$ dd bs=8192 count=1 seek=1 of=16490 if=16490
Now, log in and get the result
|
postgres=# select * from check_corruption; aid | bid | abalance | filler ———+———+—————+——————————————————————————————————————————— 1 | 1 | 0 | This is checksum example, checksum is for computing block corruption 2 | 1 | 0 | This is checksum example, checksum is for computing block corruption 3 | 1 | 0 | This is checksum example, checksum is for computing block corruption 4 | 1 | 0 | This is checksum example, checksum is for computing block corruption 5 | 1 | 0 | This is checksum example, checksum is for computing block corruption (5 rows) |
I got the result, but why?
I got the result from shared buffers. Let me restart the cluster and fetch the same.
/usr/local/pgsql/bin/pg_ctl restart -D /u01/pgsql/data
|
postgres=# select * from check_corruption; aid | bid | abalance | filler ———+———+—————+——————————————————————————————————————————— 1 | 1 | 0 | This is checksum example, checksum is for computing block corruption 2 | 1 | 0 | This is checksum example, checksum is for computing block corruption 3 | 1 | 0 | This is checksum example, checksum is for computing block corruption 4 | 1 | 0 | This is checksum example, checksum is for computing block corruption 5 | 1 | 0 | This is checksum example, checksum is for computing block corruption (5 rows) |
But again why?
As we discussed earlier, during restart my PostgreSQL has replaced error checksum with the value of shared buffer.
How can we trigger a checksum warning?
We need to get that row out of shared buffers. The quickest way to do so in this test scenario is to restart the database, then make sure we do not even look at (e.g. SELECT) the table before we make our on-disk modification. Once that is done, the checksum will fail and we will, as expected, receive a checksum error:
i.e., stop the server, corrupt the disk and start it.
- /usr/local/pgsql/bin/pg_ctl stop -D /u01/pgsql/data
- dd bs=8192 count=1 seek=1 of=16490 if=16490
- /usr/local/pgsql/bin/pg_ctl start -D /u01/pgsql/data
During the next fetch, I got below error
postgres=# select * from check_corruption;
2020-02-06 19:06:17.433 IST [25218] WARNING: page verification failed, calculated checksum 39428 but expected 39427
WARNING: page verification failed, calculated checksum 39428 but expected 39427
2020-02-06 19:06:17.434 IST [25218] ERROR: invalid page in block 1 of relation base/13455/16490
2020-02-06 19:06:17.434 IST [25218] STATEMENT: select * from check_corruption;
ERROR: invalid page in block 1 of relation base/13455/16490
Let us dig deeper into the issue and confirm that the block is corrupted
There are a couple of ways you can find the issue which includes Linux commands like
- dd
- od
- hexdump
Usind dd command : dd if=16490 bs=8192 count=1 skip=1 | od -A d -t x1z -w16 | head -1
[postgres@stagdb 13455]$ dd if=16490 bs=8192 count=1 skip=1 | od -A d -t x1z -w16 | head -2
1+0 records in
1+0 records out
8192 bytes (8.2 kB) copied, 4.5e-05 seconds, 182 MB/s
0000000 00 00 00 00 a0 fc 7e 01 03 9a 00 00 2c 00 80 1d >……~…..,…<
here,
00 00 00 00 a0 fc 7e 01 the first 8 bytes indicate pd_lsn and the next two bytes
03 9a indicates checksums.
Using hexdump : hexdump -C 16490 | head -1
[postgres@stagdb 13455]$ hexdump -C 16490 | head -1
00000000 00 00 00 00 a0 fc 7e 01 03 9a 00 00 2c 00 80 1d |……~…..,…|
[postgres@stagdb 13455]$
Both hexdump and dd returned same result.
Let’s understand what our PostgreSQL very own pg_checksums has to say?
command: pg_checksums -D /u01/pgsql/data –check
[postgres@stagdb 13455]$ pg_checksums -D /u01/pgsql/data –check
pg_checksums: error: checksum verification failed in file “/u01/pgsql/data/base/13455/16490”, block 1: calculated checksum 9A04 but block contains 9A03
Checksum operation completed
Files scanned: 968
Blocks scanned: 3013
Bad checksums: 1
Data checksum version: 1
[postgres@stagdb 13455]$
here, according to pg_checksums checksum 9A03 is matching with that of hexdump’s checksum 9A03.
Converting Hex 9A03 to decimals, I got 39427
which is matching the error
2020-02-06 19:06:17.433 IST [25218] WARNING: page verification failed, calculated checksum 39428 but expected 39427

How to resolve the PostgreSQL corrupted page issue?
use the below function to find the exact location where the page is corrupted.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
CREATE OR REPLACE FUNCTION find_bad_row(tableName TEXT) RETURNS tid as $find_bad_row$ DECLARE result tid; curs REFCURSOR; row1 RECORD; row2 RECORD; tabName TEXT; count BIGINT := 0; BEGIN SELECT reverse(split_part(reverse($1), ‘.’, 1)) INTO tabName; OPEN curs FOR EXECUTE ‘SELECT ctid FROM ‘ || tableName; count := 1; FETCH curs INTO row1; WHILE row1.ctid IS NOT NULL LOOP result = row1.ctid; count := count + 1; FETCH curs INTO row1; EXECUTE ‘SELECT (each(hstore(‘ || tabName || ‘))).* FROM ‘ || tableName || ‘ WHERE ctid = $1’ INTO row2 USING row1.ctid; IF count % 100000 = 0 THEN RAISE NOTICE ‘rows processed: %’, count; END IF; END LOOP; CLOSE curs; RETURN row1.ctid; EXCEPTION WHEN OTHERS THEN RAISE NOTICE ‘LAST CTID: %’, result; RAISE NOTICE ‘%: %’, SQLSTATE, SQLERRM; RETURN result; END $find_bad_row$ LANGUAGE plpgsql; |
Now, using the function find_bad_row(), you can find the ctid of the corrupted location.
you need hstore extension to use the function
postgres=# CREATE EXTENSION hstore;
CREATE EXTENSION
postgres=#
postgres=# select find_bad_row(‘check_corruption’);
2020-02-06 19:44:24.227 IST [25929] WARNING: page verification failed, calculated checksum 39428 but expected 39427
2020-02-06 19:44:24.227 IST [25929] CONTEXT: PL/pgSQL function find_bad_row(text) line 21 at FETCH
WARNING: page verification failed, calculated checksum 39428 but expected 39427
NOTICE: LAST CTID: (0,5)
NOTICE: XX001: invalid page in block 1 of relation base/13455/16490
find_bad_row
————–
(0,5)
(1 row)
Deleting that particular CTID will resolve the issue
postgres=# delete from check_corruption where ctid='(0,6)’;
DELETE 1
postgres=#
If deleting ctid has not worked for you, you have an alternative solution which is setting zero_damaged_pages parameter.
Example.,
postgres=# select * from master;
WARNING: page verification failed, calculated checksum 8770 but expected 8769
ERROR: invalid page in block 1 of relation base/13455/16770
postgres=#
I can’t access the data from table master as block is corrupted.
Solution:
postgres=# SET zero_damaged_pages = on;
SET
postgres=# vacuum full master;
|
postgres=# select * from master; WARNING: page verification failed, calculated checksum 8770 but expected 8769 WARNING: invalid page in block 1 of relation base/13455/16770; zeroing out page id | name | city ——+—————+—————— 1 | Orson | hyderabad 2 | Colin | chennai 3 | Leonard | newyork |
here, it cleared the damaged page and gave the rest of the result.
What your document has to say?
zero_damaged_pages (boolean): Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to on causes the system to instead report a warning, zero out the damaged page in memory, and continue processing. This behavior will destroy data, namely all the rows on the damaged page. However, it does allow you to get past the error and retrieve rows from any undamaged pages that might be present in the table. It is useful for recovering data if corruption has occurred due to a hardware or software error. You should generally not set this on until you have given up hope of recovering data from the damaged pages of a table. Zeroed-out pages are not forced to disk so it is recommended to recreate the table or the index before turning this parameter off again. The default setting is off, and it can only be changed by a superuser.
There are a couple of things to be aware when using this feature though. First, using checksums has a cost in performance as it introduces extra calculations for each data page (8kB by default), so be aware of the tradeoff between data security and performance when using it.
There are many factors that influence how much slower things are when checksums are enabled, including:
- How likely things are to be read from shared_buffers, which depends on how large shared_buffers is set, and how much of your active database fits inside of it
- How fast your server is in general, and how well it (and your compiler) are able to optimize the checksum calculation
- How many data pages you have (which can be influenced by your data types)
- How often you are writing new pages (via COPY, INSERT, or UPDATE)
- How often you are reading values (via SELECT)
The more that shared buffers are used (and using them efficiently is a good general goal), the less checksumming is done, and the less the impact of checksums on database performance will be. On an average if you enable checksum the performance cost would be more than 2% and for inserts, the average difference was 6%. For selects, that jumps to 19%. Complete computation benchmark test can be found here
Bonus
You can dump the content of the file with pg_filedump before and after the test and can use diff command to analyze data corruption
- pg_filedump -if 16770 > before_corrupt.txt
- corrupt the disk block
- pg_filedump -if 16770 > before_corrupt.txt
- diff or beyond compare both the files.

Thank you for giving your valuable time to read the above information. I hope the content served your purpose in reaching out to the blog.
Suggestions for improvement of the blog are highly appreciable. Please contact us for any information/suggestions/feedback.
If you want to be updated with all our articles
please follow us on Facebook | Twitter
Please subscribe to our newsletter.
Хочу поделиться с вами моим первым успешным опытом восстановления полной работоспособности базы данных Postgres. С СУБД Postgres я познакомился пол года назад, до этого опыта администрирования баз данных у меня не было совсем.

Я работаю полу-DevOps инженером в крупной IT-компании. Наша компания занимается разработкой программного обеспечения для высоконагруженных сервисов, я же отвечаю за работоспособность, сопровождение и деплой. Передо мной поставили стандартную задачу: обновить приложение на одном сервере. Приложение написано на Django, во время обновления выполняются миграции (изменение структуры базы данных), и перед этим процессом мы снимаем полный дамп базы данных через стандартную программу pg_dump на всякий случай.
Во время снятия дампа возникла непредвиденная ошибка (версия Postgres – 9.5):
pg_dump: Oumping the contents of table “ws_log_smevlog” failed: PQgetResult() failed.
pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989
pg_dump: The command was: COPY public.ws_log_smevlog [...]
pg_dunp: [parallel archtver] a worker process dled unexpectedly
Ошибка «invalid page in block» говорит о проблемах на уровне файловой системы, что очень нехорошо. На различных форумах предлагали сделать FULL VACUUM с опцией zero_damaged_pages для решения данной проблемы. Что же, попрробеум…
Подготовка к восстановлению
ВНИМАНИЕ! Обязательно сделайте резервную копию Postgres перед любой попыткой восстановить базу данных. Если у вас виртуальная машина, остановите базу данных и сделайте снепшот. Если нет возможности сделать снепшот, остановите базу и скопируйте содержимое каталога Postgres (включая wal-файлы) в надёжное место. Главное в нашем деле – не сделать хуже. Прочтите это.
Поскольку в целом база у меня работала, я ограничился обычным дампом базы данных, но исключил таблицу с повреждёнными данными (опция -T, —exclude-table=TABLE в pg_dump).
Сервер был физическим, снять снепшот было невозможно. Бекап снят, двигаемся дальше.
Проверка файловой системы
Перед попыткой восстановления базы данных необходимо убедиться, что у нас всё в порядке с самой файловой системой. И в случае ошибок исправить их, поскольку в противном случае можно сделать только хуже.
В моём случае файловая система с базой данных была примонтирована в «/srv» и тип был ext4.
Останавливаем базу данных: systemctl stop postgresql@9.5-main.service и проверяем, что файловая система никем не используется и её можно отмонтировать с помощью команды lsof:
lsof +D /srv
Мне пришлось ещё остановить базу данных redis, так как она тоже исползовала «/srv». Далее я отмонтировал /srv (umount).
Проверка файловой системы была выполнена с помощью утилиты e2fsck с ключиком -f (Force checking even if filesystem is marked clean):

Далее с помощью утилиты dumpe2fs (sudo dumpe2fs /dev/mapper/gu2—sys-srv | grep checked) можно убедиться, что проверка действительно была произведена:

e2fsck говорит, что проблем на уровне файловой системы ext4 не найдено, а это значит, что можно продолжать попытки восстановить базу данных, а точнее вернуться к vacuum full (само собой, необходимо примонтирвоать файловую систему обратно и запустить базу данных).
Если у вас сервер физический, то обязательно проверьте состояние дисков (через smartctl -a /dev/XXX) либо RAID-контроллера, чтобы убедиться, что проблема не на аппаратном уровне. В моём случае RAID оказался «железный», поэтому я попросил местного админа проверить состояние RAID (сервер был в нескольких сотнях километров от меня). Он сказал, что ошибок нет, а это значит, что мы точно можем начать восстановление.
Попытка 1: zero_damaged_pages
Подключаемся к базе через psql аккаунтом, обладающим правами суперпользователя. Нам нужен именно суперпользователь, т.к. опцию zero_damaged_pages может менять только он. В моём случае это postgres:
psql -h 127.0.0.1 -U postgres -s [database_name]
Опция zero_damaged_pages нужна для того, чтобы проигнорировать ошибки чтения (с сайта postgrespro):
При выявлении повреждённого заголовка страницы Postgres Pro обычно сообщает об ошибке и прерывает текущую транзакцию. Если параметр zero_damaged_pages включён, вместо этого система выдаёт предупреждение, обнуляет повреждённую страницу в памяти и продолжает обработку. Это поведение разрушает данные, а именно все строки в повреждённой странице.
Включаем опцию и пробуем делать full vacuum таблицы:
VACUUM FULL VERBOSE

К сожалению, неудача.
Мы столкнулись с аналогичной ошибкой:
INFO: vacuuming "“public.ws_log_smevlog”
WARNING: invalid page in block 4123007 of relation base/16400/21396989; zeroing out page
ERROR: unexpected chunk number 573 (expected 565) for toast value 21648541 in pg_toast_106070
pg_toast – механизм хранения «длинных данных» в Poetgres, если они не помещаются в одну страницу (по умолчанию 8кб).
Попытка 2: reindex
Первый совет из гугла не помог. После нескольких минут поиска я нашёл второй совет – сделать reindex повреждённой таблицы. Этот совет я встречал во многих местах, но он не внушал доверия. Сделаем reindex:
reindex table ws_log_smevlog

reindex завершился без проблем.
Однако это не помогло, VACUUM FULL аварийно завершался с аналогичной ошибкой. Поскольку я привык к неудачам, я стал искать советов в интернете дальше и наткнулся на довольно интересную статью.
Попытка 3: SELECT, LIMIT, OFFSET
В статье выше предлагали посмотреть таблицу построчно и удалить проблемные данные. Для начала необходимо было просмотреть все строки:
for ((i=0; i<"Number_of_rows_in_nodes"; i++ )); do psql -U "Username" "Database Name" -c "SELECT * FROM nodes LIMIT 1 offset $i" >/dev/null || echo $i; done
В моём случае таблица содержала 1 628 991 строк! По-хорошему необходимо было позаботиться о партициирвоании данных, но это тема для отдельного обсуждения. Была суббота, я запустил вот эту команду в tmux и пошёл спать:
for ((i=0; i<1628991; i++ )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog LIMIT 1 offset $i" >/dev/null || echo $i; done
К утру я решил проверить, как обстоят дела. К моему удивлению, я обнаружил, что за 20 часов было просканировано только 2% данных! Ждать 50 дней я не хотел. Очередной полный провал.
Но я не стал сдаваться. Мне стало интересно, почему же сканирование шло так долго. Из документации (опять на postgrespro) я узнал:
OFFSET указывает пропустить указанное число строк, прежде чем начать выдавать строки.
Если указано и OFFSET, и LIMIT, сначала система пропускает OFFSET строк, а затем начинает подсчитывать строки для ограничения LIMIT.Применяя LIMIT, важно использовать также предложение ORDER BY, чтобы строки результата выдавались в определённом порядке. Иначе будут возвращаться непредсказуемые подмножества строк.
Очевидно, что вышенаписанная команда была ошибочной: во-первых, не было order by, результат мог получиться ошибочным. Во-вторых, Postgres сначала должен был просканировать и пропустить OFFSET-строк, и с возрастанием OFFSET производительность снижалась бы ещё сильнее.
Попытка 4: снять дамп в текстовом виде
Далее мне в голову пришла, казалось бы, гениальная идея: снять дамп в текстовом виде и проанализировать последнюю записанную строку.
Но для начала, ознакомимся со структурой таблицы ws_log_smevlog:

В нашем случае у нас есть столбец «id», который содержал уникальный идентификатор (счётчик) строки. План был такой:
1) Начинаем снимать дамп в текстовом виде (в виде sql-команд)
2) В определённый момент времени снятия дампа бы прервалось из-за ошибки, но тектовый файл всё равно сохранился бы на диске
3) Смотрим конец текстового файла, тем самым мы находим идентификатор (id) последней строки, которая снялась успешно
Я начал снимать дамп в текстовом виде:
pg_dump -U my_user -d my_database -F p -t ws_log_smevlog -f ./my_dump.dump
Снятия дампа, как и ожидалось, прервался с той же самой ошибкой:
pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989
Далее через tail я просмотрел конец дампа (tail -5 ./my_dump.dump) обнаружил, что дамп прервался на строке с id 186 525. «Значит, проблема в строке с id 186 526, она битая, её и надо удалить!» – подумал я. Но, сделав запрос в базу данных:
«select * from ws_log_smevlog where id=186529» обнаружилось, что с этой строкой всё нормально… Строки с индексами 186 530 — 186 540 тоже работали без проблем. Очередная «гениальная идея» провалилась. Позже я понял, почему так произошло: при удаленииизменении данных из таблицы они не удаляются физически, а помечаются как «мёртвые кортежи», далее приходит autuvacuum и помечает эти строки удалёнными и разрешает использовать эти строки повторно. Для понимая, если данные в таблице меняются и включён autovacuum, то они не хранятся последовательно.
Попытка 5: SELECT, FROM, WHERE id=
Неудачи делают нас сильнее. Не стоит никогда сдаваться, нужно идти до конца и верить в себя и свои возможности. Поэтому я решил попробовать ешё один вариант: просто просмотреть все записи в базе данных по одному. Зная структуру моей таблицы (см. выше), у нас есть поле id, которое является уникальным (первичным ключом). В таблице у нас 1 628 991 строк и id идут по порядку, а это значит, что мы можем просто перербрать их по одному:
for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
Если кто не понимает, команда работает следующим образом: просматривает построчно таблицу и отправляет stdout в /dev/null, но если команда SELECT проваливается, то выводится текст ошибки (stderr отправляется в консоль) и выводится строка, содержащая ошибку (благодаря ||, которая означает, что у select возникли проблемы (код возврата команды не 0)).
Мне повезло, у меня были созданы индексы по полю id:

А это значит, что нахождение строки с нужным id не должен занимать много времени. В теории должно сработать. Что же, запускаем команду в tmux и идём спать.
К утру я обнаружил, что просмотрено около 90 000 записей, что составляет чуть более 5%. Отличный результат, если сравнивать с предыдущим способом (2%)! Но ждать 20 дней не хотелось…
Попытка 6: SELECT, FROM, WHERE id >= and id <
У заказчика под БД был выделен отличный сервер: двухпроцессорный Intel Xeon E5-2697 v2, в нашем расположении было целых 48 потоков! Нагрузка на сервере была средняя, мы без особых проблем могли забрать около 20-ти потоков. Оперативной памяти тоже было достаточно: аж 384 гигабайт!
Поэтому команду нужно было распараллелить:
for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
Тут можно было написать красивый и элегантный скрипт, но я выбрал наиболее быстрый способ распараллеливания: разбить диапазон 0-1628991 вручную на интервалы по 100 000 записей и запустить отдельно 16 команд вида:
for ((i=N; i<M; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
Но это не всё. По идее, подключение к базе данных тоже отнимает какое-то время и системные ресурсы. Подключать 1 628 991 было не очень разумно, согласитесь. Поэтому давайте при одном подключении извлекать 1000 строк вместо одной. В итоге команда преобразилоась в это:
for ((i=N; i<M; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
Открываем 16 окон в сессии tmux и запускаем команды:
1) for ((i=0; i<100000; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
2) for ((i=100000; i<200000; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
…
15) for ((i=1400000; i<1500000; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
16) for ((i=1500000; i<1628991; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
Через день я получил первые результаты! А именно (значения XXX и ZZZ уже не сохранились):
ERROR: missing chunk number 0 for toast value 37837571 in pg_toast_106070
829000
ERROR: missing chunk number 0 for toast value XXX in pg_toast_106070
829000
ERROR: missing chunk number 0 for toast value ZZZ in pg_toast_106070
146000
Это значит, что у нас три строки содержат ошибку. id первой и второй проблемной записи находились между 829 000 и 830 000, id третьей – между 146 000 и 147 000. Далее нам предстояло просто найти точное значение id проблемных записей. Для этого просматриваем наш диапазон с проблемными записями с шагом 1 и идентифицируем id:
for ((i=829000; i<830000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR: unexpected chunk number 2 (expected 0) for toast value 37837843 in pg_toast_106070
829449
for ((i=146000; i<147000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR: unexpected chunk number ZZZ (expected 0) for toast value XXX in pg_toast_106070
146911
Счастливый финал
Мы нашли проблемные строки. Заходим в базу через psql и пробуем их удалить:
my_database=# delete from ws_log_smevlog where id=829417;
DELETE 1
my_database=# delete from ws_log_smevlog where id=829449;
DELETE 1
my_database=# delete from ws_log_smevlog where id=146911;
DELETE 1
К моему удивлению, записи удалились без каких-либо проблем даже без опции zero_damaged_pages.
Затем я подключился к базе, сделал VACUUM FULL (думаю делать было необязательно), и, наконец, успешно снял бекап с помощью pg_dump. Дамп снялся без каких либо ошибок! Проблему удалось решить таким вот тупейшим способом. Радости не было предела, после стольких неудач удалось найти решение!
Благодарности и заключение
Вот такой получился мой первый опыт восстановления реальной базы данных Postgres. Этот опыт я запомню надолго.
Ну и напоследок, хотел бы сказать спасибо компании PostgresPro за переведённую документацию на русский язык и за полностью бесплатные online-курсы, которые очень сильно помогли во время анализа проблемы.
Description
pg_verifybackup используется для проверки целостности резервной копии кластера базы данных, pg_basebackup с помощью pg_basebackup, по сравнению с backup_manifest , созданным сервером во время резервного копирования. Резервная копия должна храниться в «простом» формате; резервную копию в формате tar можно проверить после ее распаковки.
Важно отметить,что проверка,выполняемая pg_verifybackup,не включает и не может включать все проверки,которые будет выполнять работающий сервер при попытке использования резервной копии.Даже если вы используете этот инструмент,вам все равно следует выполнить тестовое восстановление и убедиться,что полученные базы данных работают так,как ожидалось,и содержат правильные данные.Однако pg_verifybackup может обнаружить множество проблем,которые обычно возникают из-за проблем с хранением или ошибок пользователя.
Проверка резервной копии проходит в четыре этапа. Сначала pg_verifybackup читает файл backup_manifest . Если этот файл не существует, не может быть прочитан, имеет неправильный pg_verifybackup или не прошел проверку по собственной внутренней контрольной сумме, pg_verifybackup завершится с фатальной ошибкой.
Во-вторых, pg_verifybackup попытается проверить, что файлы данных, хранящиеся в настоящее время на диске, в точности совпадают с файлами данных, которые сервер намеревался отправить, за некоторыми исключениями, которые описаны ниже. Будут обнаружены лишние и отсутствующие файлы, за некоторыми исключениями. На этом шаге будет игнорироваться наличие, отсутствие или любые модификации postgresql.auto.conf , standby.signal и recovery.signal , поскольку ожидается, что эти файлы могли быть созданы или изменены в процессе принятия резервная копия. Он также не будет жаловаться на файл backup_manifest в целевом каталоге или на что-либо внутри pg_wal ., даже если эти файлы не будут перечислены в манифесте резервной копии. Проверяются только файлы; наличие или отсутствие каталогов не проверяется, кроме как косвенно: если каталог отсутствует, любые файлы, которые он должен был содержать, обязательно также будут отсутствовать.
Затем pg_verifybackup вычислит контрольную сумму всех файлов, сравнит контрольные суммы со значениями в манифесте и выдаст ошибки для любых файлов, для которых вычисленная контрольная сумма не соответствует контрольной сумме, хранящейся в манифесте. Этот шаг не выполняется для файлов, которые привели к ошибкам на предыдущем шаге, поскольку уже известно, что они содержат проблемы. Файлы, которые были проигнорированы на предыдущем шаге, также игнорируются на этом шаге.
Наконец, pg_verifybackup будет использовать манифест, чтобы убедиться, что записи журнала упреждающей записи, которые потребуются для восстановления резервной копии, присутствуют и что они могут быть прочитаны и проанализированы. backup_manifest содержит информацию о том, какие записи вперед входа будут необходимы записи, и pg_verifybackup будет использовать эту информацию , чтобы вызвать pg_waldump разобрать эти записи вперед записи в Журнал. --quiet флаг будет использоваться, так что pg_waldump будет сообщать только об ошибках, без каких-либо других выводов. Хотя этого уровня проверки достаточно для обнаружения очевидных проблем, таких как отсутствующий файл или файл, чьи внутренние контрольные суммы не совпадают, он недостаточно обширен, чтобы обнаружить все возможные проблемы, которые могут возникнуть при попытке восстановления. Например, ошибка сервера, которая создает записи журнала упреждающей записи, которые имеют правильные контрольные суммы, но указывают бессмысленные действия, не может быть обнаружена этим методом.
Обратите внимание, что если присутствуют дополнительные файлы WAL, которые не требуются для восстановления резервной копии, они не будут проверяться этим инструментом, хотя для этой цели можно использовать отдельный вызов pg_waldump . Также обратите внимание, что проверка WAL зависит от версии: вы должны использовать версию pg_verifybackup и, следовательно, pg_waldump , которая относится к проверяемой резервной копии. Напротив, проверки целостности файла данных должны работать с любой версией сервера, который генерирует файл backup_manifest .
Examples
Чтобы создать базовую резервную копию сервера на mydbserver и проверить целостность резервной копии:
$ pg_basebackup -h mydbserver -D /usr/local/pgsql/data $ pg_verifybackup /usr/local/pgsql/data
Чтобы создать базовую резервную копию сервера на mydbserver , переместите манифест куда-нибудь за пределы каталога резервных копий и проверьте резервную копию:
$ pg_basebackup -h mydbserver -D /usr/local/pgsql/backup1234 $ mv /usr/local/pgsql/backup1234/backup_manifest /my/secure/location/backup_manifest.1234 $ pg_verifybackup -m /my/secure/location/backup_manifest.1234 /usr/local/pgsql/backup1234
Проверка резервной копии с игнорированием файла,который был добавлен в каталог резервных копий вручную,а также пропуском проверки контрольной суммы:
$ pg_basebackup -h mydbserver -D /usr/local/pgsql/data $ edit /usr/local/pgsql/data/note.to.self $ pg_verifybackup --ignore=note.to.self --skip-checksums /usr/local/pgsql/data