Задача: OLV-4416. Единственный carrier этого runbook — runbooks:srv-postgre-olvr; он заменяет прежний указатель srv-postgre.olvr.md из sysmanage.
Статус: DR-only. Standby не квалифицирован как горячая замена primary. Collation mismatch не устранён; готовность failover и приемлемый численный RTO не доказаны.
Этот документ описывает ограничения и условную будущую recovery-операцию. Его публикация не разрешает promotion, REINDEX, REFRESH, изменение БД, доступов или конфигурации. Реальная операция требует назначения оператора, проверки target и отдельного разрешения владельца на production writes.
srv-postgre.olvr, 192.168.176.9:5432, socket /var/tmp/pgsql-standby; PostgreSQL 17.9, FreeBSD 14.3.srv-prod-postgre.olvr; установленный hostname pgsql-ng, Debian 11, glibc 2.31-13+deb11u6.datcollversion=2.31, версия collation на standby — 43.0. WARNING при подключении сообщает об этом риске.srv-postgre.olvr есть также тестовый инстанс: вызов psql без явного endpoint может обратиться не к standby. Для standby использовать только подтверждённый endpoint; имя host само по себе не подтверждает инстанс.Факты — датированные результаты DESIGN YqIv/gvQSwN и принятых измерений NGw4/9jyCrC от 02.10.2026, а не новая проверка состояния сервера при чтении этого документа.
Не использовать standby для сверок, аналитики и любых выборок, где важна корректность результата по текстовым ключам или текстовому порядку. Индексы построены с правилами сортировки primary; библиотека standby может иначе упорядочивать те же ключи. Возможны неверные результаты поиска и порядка.
Вместо standby использовать primary через существующий разрешённый read-only доступ (например, роль monitoring, если доступ подтверждён для нужной базы) либо разрешённую выгрузку с primary. Этот runbook новых прав доступа не выдаёт.
Технический запрет через pg_hba и автоматическое отключение мониторинга не вводятся. Подтверждённый потребитель standby — локальный postgres_exporter, роль prometheus, соединение с явным standby socket. Его наличие не означает, что все периодические читатели установлены.
Операционный получатель уведомления — РП OLVR: ограничения приняты, мониторинг не отключать. Внешний владелец exporter отдельно не установлен; этот gap передан OLVR без нового inventory.
Отсутствие WARNING после REFRESH не доказывает корректности индексов или размещения строк. REFRESH меняет метаданные версии, но зависимые объекты не исправляет.
Определение одинаково для индексов и range-ключей:
pg_collation.collprovider = 'c' (libc), locale не C/POSIX;collprovider = 'i' (ICU);collprovider = 'd' (default базы), если pg_database.datlocprovider = 'i' либо datlocprovider = 'c' с datcollate не C/POSIX.
Не входят: provider b (builtin), C/POSIX и не-collatable ключи.
ICU включена намеренно: равенство библиотек ICU на primary и standby не доказано. Это сохранённая fail-closed граница принятого DESIGN, а не разрешение переходить на ICU или поручение проверять её версии. Новый алгоритм классификации здесь не вводится.
В 30 измеренных базах, включая template1:
pg_relation_size — 1 122 320 384 bytes (около 1,045 GiB);
template0 не измерена: подключение фактически отклонено. Ноль относится только к 30 измеренным базам. template0 не квалифицирована как источник клонирования; без отдельной будущей qualification её нельзя использовать как проверенный cloning source или включать в заявление о полной готовности recovery. Открывать её или менять datallowconn ради настоящего документа нельзя.
Время REINDEX и численный RTO не измерены. Только сценарная чувствительность компонента по объёму: V / v_eff, где V = 1 070,328125 MiB. При условных 10 / 50 / 100 MiB/s это примерно 107,03 / 21,41 / 10,70 секунды. Эти скорости — предположения, не замер данного host и не обещанный диапазон производительности. Полная добавка к RTO включает чтение heap, сортировку, WAL, конкуренцию за ресурсы и накладные расходы; они не измерены.
Приложения не подключать на запись до завершения соответствующей ветки и проверки корректности. Процедура ниже — документ будущей разрешённой операции, не команда исполнять её сейчас.
После разрешённого pg_promote() / pg_ctl promote в каждой базе повторить запрос ниже. Использовать актуальное состояние на момент аварии, а не прошлый нулевой снимок NGw4. template1 входит в проверку; предел template0 сохраняется отдельно.
SELECT n.nspname, c.relname, pg_get_partkeydef(c.oid) AS partkey FROM pg_partitioned_table p JOIN pg_class c ON c.oid = p.partrelid JOIN pg_namespace n ON n.oid = c.relnamespace WHERE p.partstrat = 'r' AND EXISTS ( SELECT 1 FROM unnest(p.partcollation::oid[]) AS k(coll) JOIN pg_collation co ON co.oid = k.coll JOIN pg_database d ON d.datname = current_database() WHERE (co.collprovider = 'c' AND co.collcollate NOT IN ('C', 'POSIX')) OR co.collprovider = 'i' OR (co.collprovider = 'd' AND (d.datlocprovider = 'i' OR (d.datlocprovider = 'c' AND d.datcollate NOT IN ('C', 'POSIX')))));
Не-collatable ключи с oid 0 отсекаются join; builtin и C/POSIX не выбираются. List/hash-разбиение не входит в принятую проверку порядка при детерминированной collation.
Если найден хотя бы один range-ключ с затронутой collation, этот recovery-рецепт недостаточен. Приложения на запись не подключать.
REINDEX не перемещает строки между разделами. До включения записи требуется проверить/исправить размещение строк найденных таблиц либо получить решение о совместимом target. Список таблиц немедленно передать OLVR/Борису. Проектирование repartitioning этим runbook не выполняется; перенос на Linux не разрешён решением владельца.
Если актуальная выборка пуста во всех проверенных базах, в каждой базе, включая template1, выполнить REINDEX индексов с затронутой collation. Принятый контракт допускает REINDEX DATABASE для соответствующей базы.
Не выдавать это условие за выполненное для template0: её техническая граница требует отдельного disposition и будущей qualification. Не объявлять полную готовность всех баз при сохраняющемся пробеле.
После перестроения выполнить для каждой соответствующей базы:
ALTER DATABASE <db> REFRESH COLLATION VERSION;
<db> — placeholder фактического, корректно экранированного имени базы, а не буквальная команда. REFRESH сам по себе не исправляет индексы или range-размещение.
В рамках той же разрешённой recovery-операции: CREATE EXTENSION IF NOT EXISTS amcheck, затем bt_index_check по индексам с затронутой collation — без ошибок. Это будущие изменяющие/проверочные действия; сейчас они не выполнялись.
Проверка отсутствия WARNING при новом подключении касается только metadata. Она не заменяет amcheck и не снимает ветку остановки при range partitions.
Только после необходимого REINDEX, REFRESH и успешной проверки корректности подключать приложения на запись. При непустой range-выборке сначала обязательно завершить ветку проверки/исправления размещения либо получить решение о совместимом target. Непроверенную template0 не включать в обещание полной готовности или безопасного клонирования.
Борис через OLVR, YqIv/lFILCU: «4416 — никаких линуксов не будет». Перенос standby на Linux исключён. Переход на ICU не разрешён.
Отказ от Linux не означает устранения mismatch, приемлемого RTO или готовности горячей замены. Долгосрочное решение и технический disposition template0 остаются за OLVR/Борисом в OLV-4416. Jira пока не закрывать как устранённую.
Риск той же природы возникнет на primary при будущей смене ОС/glibc srv-prod-postgre.olvr. До такого изменения учитывать зависимость индексов и range-размещения от правил collation.
Публикация этого runbook — документационный результат, не выполнение recovery и не устранение collation mismatch.