Postgres ctid, чтобы блокировать несоответствие количества - PullRequest
0 голосов
/ 15 января 2020

Я использую Postgres 9.4.5, и я обнаружил повреждение в одной из моих таблиц. Я заметил это, когда выполнение запросов к определенной таблице c привело к тому, что вся база данных go перешла в режим восстановления. Симптомы совпадают с симптомами, описанными в этой статье:

https://www.endpoint.com/blog/2010/06/01/tracking-down-database-corruption-with

Я попытался выполнить шаги, чтобы обнулить поврежденный блок, но после выполнения шагов я получил ctid 507578.

database=# \set FETCH_COUNT 1
database=# \pset pager off
Pager usage is off.
database=# SELECT ctid, left(coded_element_key::text, 20) FROM coded_element WHERE ctid >= '(507577,1)';
    ctid    |   left   
------------+----------
 (507577,1) | 30010491
 (507577,2) | 30010507
 (507577,3) | 30010552
 (507577,4) | 30010556
 (507577,5) | 30010559
 (507577,6) | 30010564
 (507577,7) | 30010565
 (507577,8) | 30010625
 ...
 ...
 ...
 (507578,26) | 0A1717281.0002L270&.
 (507578,27) | L270&.*)0000.0000000
 (507578,28) | 30011452
 (507578,29) | -L0092917\x10)*(0117001
 (507578,30) | 0.00003840\x10)*)300114
ERROR:  invalid memory alloc request size 1908473862

Проблема в том, что, когда я зашел в свой каталог / data / base и нашел соответствующий файл для моей таблицы, файл был только 1073741824 байта. С размером блока 8192 байта это дает мне счетчик блоков только 131072, что значительно ниже значения 507578, где предполагаемое искажение. Это правильный способ определения смещения блока или есть другой способ?

1 Ответ

0 голосов
/ 15 января 2020

PostgreSQL сохраняет данные таблицы в файлах размером 1 ГБ.

Если предположить, что результат

SELECT relfilenode
FROM pg_class
WHERE relname = 'coded_element';

равен 12345, эти файлы будут называться 12345, 12345.1, 12345.2 и т. Д.

Поскольку каждый из этих сегментов 1 ГБ содержит 131072 блоков, блок 507578 фактически является блоком 114362 в 12345.4.

Повреждение данных либо в том, что или следующий.

На этом этапе убедитесь, что у вас есть резервная копия полного каталога данных.

Чтобы обнулить блок 507578, вы можете использовать

dd if=/dev/zero of=12345.4 bs=8192 seek=114362 count=1 conv=notrunc,nocreat,fsync

Если это не помогает, попробуйте следующий блок.

Чтобы сохранить данные из блока перед его обнулением, вы можете использовать расширение pageinspect.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...