Ошибка 1с базы данных PostgreSQL: missing chunk number 0 for toast value * in pg_toast_*
Далее описан процесс восстановление базы данных 1С PostgreSQL. Ошибки базы данных не позволяли делать выгрузку базы в файл dt через конфигуратор и не позволяли делать резервную копию через pg_dump.
ОШИБКА: 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 в чистую базу, рассмотрим в следующей статье.
- Комментарии
Загрузка комментариев...