Ошибка 1с базы данных PostgreSQL: missing chunk number 0 for toast value * in pg_toast_*
Далее описан процесс восстановление базы данных 1С PostgreSQL. Ошибки базы данных не позволяли делать выгрузку базы в файл dt через конфигуратор и не позволяли делать резервную копию через pg_dump.
В данном примере ошибка содержится в таблице public._datahistoryqueue0
ОШИБКА: missing chunk number 0 for toast value 645974 in pg_toast_32747 и другие ошибки похожие ошибки
Вкратце: при записи объекта, версии которого должны сохраняться в Истории данных, информация о значениях реквизитов и табличных частях объекта сохраняется в таблицу `_DataHistoryQueue0`. Из этой таблицы-очереди данные должны переноситься в таблицу `_DataHistoryVersions` по команде `ИсторияДанных.ОбновитьИсторию();` или сразу при включенной опции «Обновлять историю данных сразу после записи».
Основная задача - удалить битую или битые строки из данной таблицы. Перед и после всех манипуляций, обязательная резервная копия базы данных. В данном случае остается только вариант копирования папки Data PostgreSQL.
Информация по таблице через ANALYZE в Postgres через pgAdmin
Строк в таблице - 31 973 047 Таблица datahistoryqueue0 имеет структуру
Можно делать периодическую выборку в поисках нужной строки и с сортировкой по нужному полю, так как уникального ид, к сожалению, нет в данной таблице, то единственный вариант остается это использование ctid, сортировка, выборка по нему и удаление строк.
ctid - Физическое расположение данной версии строки в таблице. По ctid можно очень быстро найти версию строки, значение ctid изменится при выполнении VACUUM FULL. Таким образом, ctid нельзя применять в качестве долгосрочного идентификатора строки. Для идентификации логических строк следует использовать первичный ключ.
Пример команды выборки данных 0+5000 строк, с сортировкой по ctid
select ctid from public._datahistoryqueue0 order by ctid limit 5000 offset 0Обходить таблицу вручную из 31 млн. в поисках сбойных строк слишком долго и не продуктивно, поэтому будем использовать готовую пользовательскую функцию
Добавляем пользовательскую функцию
Открываем pgAdmin, кликаем правой кнопкой мышки на нужную базу данных и открываем ЗапросникСначала добавляем расширение hstore оно необходимо для работы. Прописываем и нажимаем кнопку выполнить.
CREATE EXTENSION hstore;Добавляем данную функцию и нажимаем выполнить
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;
После этого функция сохранится и её можно будет использовать
1. Запускаем функцию и указываем проблемную таблицу
select find_bad_row('public._datahistoryqueue0');
Скрипт проходит по всем записям в данной таблице, расширяет их одну за другой – что приведет к исключению, если произойдет какая-либо ошибка расширения. Исключение также будет содержать CTID последней правильно обработанной строки. И следующая строка с более высоким CTID будет поврежденной.
Результат запроса – первая ошибка
1.1. Проверяем проблемную строку указывая ctid 322081,18 следующей за 322081,17
select * from public._datahistoryqueue0 where ctid = '(322081,18)';
1.2. Строчка найдена, удаляем её
delete from public._datahistoryqueue0 where ctid = '(322081,18)';2. Снова запускаем функцию и находим следующую проблемную строку
select find_bad_row('public._datahistoryqueue0');
2.1. Проверяем проблемную строку указывая ctid следующей строки
select * from public._datahistoryqueue0 where ctid = '(322082,6)';
2.2. Строчка найдена, удаляем её
delete from public._datahistoryqueue0 where ctid = '(322082,6)';3. Снова запускаем функцию и находим следующую проблемную строку
select find_bad_row('public._datahistoryqueue0');
3.1. Проверяем проблемную строку указывая ctid следующей строки
select * from public._datahistoryqueue0 where ctid = '(406052,19)';
3.2. Строчка найдена, удаляем её
delete from public._datahistoryqueue0 where ctid = '(406052,19)';4. Снова запускаем функцию и находим следующую проблемную строку
select find_bad_row('public._datahistoryqueue0');
4.1. Проверяем проблемную строку указывая ctid следующей строки
select * from public._datahistoryqueue0 where ctid = '(406052,21)';
4.2. Строчка найдена, удаляем её
delete from public._datahistoryqueue0 where ctid = '(406052,21)';5. Снова запускаем функцию и находим следующую проблемную строку
select find_bad_row('public._datahistoryqueue0');
5.1. Проверяем проблемную строку указывая ctid следующей строки
select * from public._datahistoryqueue0 where ctid = '(468277,28)';
5.2. Строчка найдена, удаляем её
delete from public._datahistoryqueue0 where ctid = '(468277,28)';Больше ошибок в данной таблице не было
Итого было найдено и удалено битых строк - 5 шт. (потеря истории 5 шт. из 31 973 047 шт. ничтожно мала)
Результат
База данных исправлена, резервное копирование базы данных через pg_dump успешно выполнено. Также база успешно выгружается из конфигуратора в файл dt.Устранение ошибок при загрузке файла dt в чистую базу, рассмотрим в следующей статье.
- Комментарии
Загрузка комментариев...
















