«Invalid page» и «тост»

Недавно у одного из клиентов развалилась часть таблицы в «Постгресе» — в логах видно, что при чтении не совпадают контрольные суммы. Ничего особо нового — за последние несколько лет встречал эту проблему несколько раз у разных клиентов и даже описал алгоритм восстановления базы из разных источников у себя на сайте.

Там у меня в заметке есть хранимая функция, которая сканирует таблицу и сообщает какие именно строки требуется восстановить. Но в этот раз она мне, как ни странно, не помогла — завершилась, не выдав ничего. Раньше она осечек не давала и я, не поверив себе, даже запустил её дважды.

Долго разбирался в чём дело, разобрался. Принцип работы моей функции такой — она вынимает каждую строку, если получает ошибку, то сообщает об этом. Но оказалось, что если какие-либо разрушенные данные лежат в «тостах» (это механизм автоматического сжатия и выноса больших значений полей в «Постгресе»), то этого недостаточно. Видимо «Постгрес» в реальности не достаёт эти данные, пока они не понадобятся для чего-либо и поэтому ошибки не возникает.

В итоге я переделал хранимку — передаю всё строку целиком в функцию ROW_TO_JSON, чтобы прочитались и значения из «тостов». Это помогло, функция стала работать как и задумывалось.

CREATE OR REPLACE FUNCTION check_table(table_name TEXT)
RETURNS void AS $$
DECLARE
    rec RECORD;
    row_data RECORD;
BEGIN
    FOR rec IN EXECUTE format('SELECT ctid::text AS ctid_str, id FROM %I', table_name)
    LOOP
        BEGIN
            EXECUTE format('SELECT * FROM %I WHERE ctid = %L::tid', table_name, rec.ctid_str)
            INTO STRICT row_data;

        row_data := ROW(ROW_TO_JSON(row_data)); /* to read the toasts */

        EXCEPTION WHEN others THEN
            RAISE WARNING 'CTID: %, ID: %, Error: %', rec.ctid_str, rec.id, SQLERRM;
        END;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

2 комментария

«Кардпьютер» и джойстик

Так я и не смог заказать нужный мне джойстик к «Кардпьютеру» — как я уже рассказывал везде конец истории один — отправляю деньги, продавец выжидает, потом отменяет заказ, деньги возвращаются. В итоге сделал ход конём — купил джойстик другой версии и просто дописал прошивку, чтобы она его поддерживала.

Оказалось несложно — я нашёл коммит, где добавили поддержку другого джойстика, там очень понятный код. Заработало сразу почти правильно, только пришлось поменять верх и низ местами. Эмулятор я пока не нашёл (если предположить, что он существует), а сама прошивка компилируется очень просто, запишу себе, чтобы не забыть:

# установка всех нужных инструментов
curl -fsSL -o get-platformio.py \
https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
python3 get-platformio.py

# сборка прошивки
~/.platformio/penv/bin/pio run
Белый карманный компьютер Cardputer ADV с клавиатурой, экраном и модулем StampS3A, подключённый к джойстику через многоцветный кабель на коричневом фоне.

Добавлено 12 февраля: о, мой код по поддержки джойстика этой версии вмержили внутрь прошивки пакета эмуляторов. Теперь можно скачивать новые версии без необходимости их патчить!

Оставить комментарий