PostgreSQL 8.3.11 заблокирован; восстановление потерянного объекта базы данных pg_toast

Привет Slack Overflowvians.

Итак, я наткнулся на этот сервер PostgreSQL под управлением 8.3.11 (да, я знаю), который был в заблокированном состоянии с:

ERROR:  database is not accepting commands to avoid wraparound data loss in database "postgres"
HINT:  Stop the postmaster and use a standalone backend to vacuum that database.

Обычно с этим справляется демон автоматической очистки (autovacuum=on), но поскольку следующие четыре TOAST (позволяют хранить большие значения полей размером 8 КБ, например хлеб), объект базы данных. Но XID этой базы данных никогда не сбрасывался из-за этих поврежденных объектов базы данных.

Ниже приведен фрагмент вывода при запуске сервера в однопользовательском режиме с правами администратора:

SELECT oid, relname, age(relfrozenxid) FROM pg_class WHERE relkind = 't' ORDER BY age(relfrozenxid) DESC LIMIT 4;


    ----
     1: oid = "2421459"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421456"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421450"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421447"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421435"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421432"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421426"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421423"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)

Обратите внимание, что возраст значительно превышает vacuum_freeze_min_age (значение, установленное после успешного VACUUM) на этом сервере и, следовательно, почему он выдает исходные ошибки, указанные выше. Вышеупомянутое было ПОСЛЕ запуска VACUUM FULL; все остальные таблицы в порядке.

SELECT relfilenode FROM pg_class WHERE oid=2421459;

Итак, когда мы посмотрели на диск (использовали значение pg_class.relfilenode для каждой таблицы выше), файл таблицы всплывающих уведомлений отсутствовал:

$ find /var/lib/pgsql/data/ -type f -name '2421426' | wc -l  # Bad toast
0

и когда мы посмотрели на диске индекс тоста

 SELECT relfilenode FROM pg_class WHERE (select reltoastidxid FROM pg_class WHERE oid=2421459)

$ find /var/lib/pgsql/data/ -type f -name '2421459' | wc -l  # Bad toast's index
0

Затем мы попытались найти таблицу, с которой связана плохая запись всплывающего уведомления:

SELECT * FROM pg_class WHERE reltoastrelid=2421459;

получил 0 результатов для каждой таблицы выше! Нет таблиц для команды VACUUM для сброса XID этих отношений.

Когда мы проверили таблицу pg_depend и обнаружили, что в этих таблицах TOAST НЕТ ссылок:

SELECT * FROM pg_depend WHERE refobjid IN(2421459,2421450,2421435,2421426)

Вопрос

  1. Можете ли вы удалить плохую таблицу TOAST и индексы таблицы TOAST из таблицы pg_class (например, DELETE FROM pg_class where oid=2421459)
  2. Есть ли какие-либо другие таблицы, из которых нам также нужно удалить отношение?
  3. Можем ли мы просто создать временную таблицу и связать ее с oid индекса TOAST?

Пример для № 3 выше:

CREATE TABLE adoptedparent (colnameblah char(1));
UPDATE pg_class SET reltoastrelid=2421459 WHERE relname='adoptedparent';  
VACUUM FULL VERBOSE adoptedparent

ИЗМЕНИТЬ:

select txid_current() равно 3094769499, поэтому эти таблицы были давно повреждены. Нам не нужно восстанавливать данные. Мы используем файловую систему ext4 на Linux 2.6.18-238.el5. Мы проверили соответствующие каталоги lost+found/, и файлов там не было.


person Yzmir Ramirez    schedule 30.09.2015    source источник
comment
Интересно, имеет ли смысл спрашивать об этом в другом сообществе обмена Slack, поскольку это так database ориентировано?   -  person Yzmir Ramirez    schedule 30.09.2015


Ответы (1)


Просто для домашней аудитории, в данном конкретном случае решением было напрямую отредактировать pg_class. И, конечно же, обновите сервер до поддерживаемой версии Postgres!

Конкретные ответы:

  1. Да, вы можете, хотя в большинстве случаев лучше создать пустую таблицу, прикрепить к этой таблице отношение toast, добавить записи pg_depend и удалить таблицу. В данном случае это не имело смысла, потому что действительно не было других объектов, зависящих от этих тост-столов.

    1. Обычно всплывающие таблицы также имеют индекс в pg_index и записи в pg_depend. Это не так.

    2. См. выше.

person FuzzyChef    schedule 01.10.2015