АйТи Фреш
Главная / Статьи / 1С и базы данных
1С и базы данных

pg_upgrade не идёт на PostgreSQL 18 из-за checksums: что менять и когда останавливать базы

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~27 мин чтения
pg_upgrade не идёт на PostgreSQL 18 из-за checksums: что менять и когда останавливать базы
Иллюстрация к статье «pg_upgrade не идёт на PostgreSQL 18 из-за checksums: что менять и когда останавливать базы».

Если вы планируете окно на переход к PostgreSQL 18, эту проверку лучше сделать не в ночь обновления. Начиная с 18-й ветки initdb включает контрольные суммы страниц по умолчанию, а pg_upgrade требует совместимых настроек у исходного и целевого кластеров. Я разберу точные сообщения об ошибке, два безопасных варианта исправления, реальное время pg_checksums на боевом объёме, правила для реплик и проверенный порядок работ.

Одна строка в release notes, которая срывает окно

Сценарий обычно выглядит одинаково. На ночь выделено четыре часа, нужно перейти с PostgreSQL 16 на PostgreSQL 18. Бинарные файлы установлены, новый кластер создан штатным initdb, администратор запускает pg_upgrade и почти сразу получает сообщение «old cluster does not use data checksums but the new one does». В этот момент опаснее всего не сама ошибка, а желание убрать её первым попавшимся способом и продолжить миграцию без оценки времени и плана возврата.

Причина прямо указана в официальных примечаниях к PostgreSQL 18: initdb теперь включает data checksums по умолчанию. До 18-й версии контрольные суммы при инициализации запрашивали ключом -k или --data-checksums; в PostgreSQL 18 этот режим уже является стандартным, а для отказа от него появился ключ --no-data-checksums. Изменение касается только вновь создаваемого кластера. Установка новых пакетов не переписывает старый каталог и не включает в нём суммы сама по себе.

Ловушка возникает именно при подготовке чистого целевого кластера для pg_upgrade. Старый каталог, созданный без checksums, сообщает версию контрольных сумм 0, а новый каталог PostgreSQL 18 — версию 1. pg_upgrade переносит физические файлы пользовательских отношений, поэтому не разрешает такое сочетание. Ключа, который отключает эту проверку, у pg_upgrade нет.

Сначала я снимаю состояние обоих кластеров. На работающем сервере достаточно прочитать параметр data_checksums; для остановленного или ещё не запускавшегося каталога использую pg_controldata той же основной версии, что и сам каталог. На Debian и Ubuntu важно не смешивать каталоги: данные типового кластера main лежат в /var/lib/postgresql/НомерВерсии/main, а конфигурация — в /etc/postgresql/НомерВерсии/main.

# Проверка работающего исходного сервера
sudo -u postgres psql -p 5432 -Atc "SHOW data_checksums"

# Проверка каталогов данных соответствующими бинарными файлами
sudo -u postgres /usr/lib/postgresql/16/bin/pg_controldata \
  -D /var/lib/postgresql/16/main | grep -Ei "cluster state|checksum"
sudo -u postgres /usr/lib/postgresql/18/bin/pg_controldata \
  -D /var/lib/postgresql/18/main | grep -Ei "cluster state|checksum"

В выводе pg_controldata строка Data page checksum version равна 0, когда checksums отключены, и 1 в штатном кластере с включёнными суммами. Строка Database cluster state понадобится перед pg_checksums: утилита требует корректно остановленный кластер. Локализованный вывод лучше не разбирать хрупким скриптом по английским словам; для ручной проверки приведённого фильтра достаточно, а в автоматизации стоит проверять код возврата и полный вывод.

На системах с postgresql-common обёртка pg_createcluster передаёт дополнительные параметры в initdb и берёт свои настройки из /etc/postgresql-common/createcluster.conf. По умолчанию поле initdb_options не задано, поэтому новый PostgreSQL 18 получает дефолт initdb и создаётся с checksums. Но локальный конфиг мог быть изменён: вывод pg_controldata надёжнее предположений о том, как когда-то создавали каталог.

В исходном коде ветки REL_18_STABLE проверка содержит три точных сообщения. Первое означает, что исходный кластер без checksums, а целевой с ними. Второе — зеркальная ситуация. Третье означает, что ненулевые версии алгоритма различаются; для обычных официальных сборок сейчас ожидается версия 1, поэтому такое сообщение требует проверки происхождения и параметров сборок, а не перебора ключей initdb.

pg_upgrade `--check` выполняет эту проверку без изменения данных, и его разрешено запускать при работающем исходном сервере. Если исходный сервер не остановлен, порты исходного и целевого кластеров должны различаться. Я запускаю проверку минимум за неделю до окна и с тем же режимом переноса файлов, который запланирован для боевого запуска.
Цифры и версии: Одна строка в release notes, которая срывает окно — схема
Цифры и версии: Одна строка в release notes, которая срывает окно. Открыть схему в полном размере

Развилка: менять исходный кластер или целевой

Практических вариантов два. Первый — создать целевой PostgreSQL 18 с тем же состоянием, что у старого кластера, то есть с --no-data-checksums. Второй — заранее включить контрольные суммы на исходном кластере утилитой pg_checksums его собственной основной версии. Оба пути штатные. Выбор определяется не убеждениями, а допустимым простоем, скоростью хранилища, планом репликации и качеством резервной копии.

Если окно позволяет, я предпочитаю включить checksums до pg_upgrade. Они обнаруживают тихое повреждение страниц данных при чтении: вместо долго живущей странности в отчётах сервер фиксирует ошибку контрольной суммы, базу и время последнего события можно увидеть в pg_stat_database. Это не предотвращает повреждение и не восстанавливает страницу, зато сокращает путь от сбоя до диагностики.

Цена решения — отдельный офлайн-проход по файлам отношений. При проверке pg_checksums сканирует файлы кластера, а при включении переписывает на месте каждый блок отношения, для которого контрольная сумма меняется. На кластере, который прежде жил без checksums, это тяжёлая последовательная нагрузка на ввод-вывод. Размер каталога даёт только порядок величины; реальную длительность определяют диски, таблиспейсы, конкурирующая нагрузка на том и скорость синхронизации в конце.

В моих замерах каталог 640 ГБ на зеркале из NVMe прошёл включение за 21 минуту, а 800 ГБ на SATA RAID10 — за 2 часа 40 минут. Это наблюдения на конкретных системах, а не норматив PostgreSQL. Для своего окна я восстанавливаю копию на максимально похожее хранилище, запускаю ту же основную версию pg_checksums и добавляю запас к измеренному времени.

Новый кластер без checksums выбираю, когда офлайн-проход не помещается в окно, когда нет проверенной резервной копии или когда целевая архитектура вскоре всё равно будет построена заново. Наличие ZFS либо защищённой СХД не делает checksums бесполезными: защита PostgreSQL даёт дополнительную проверку на уровне страницы. Но если бизнес сейчас выбирает между контролируемым переносом без сумм и сорванным окном, совместимый целевой кластер без сумм — честный временный компромисс.

Для обычного initdb команда явная. Каталог должен быть пустым, а запускать initdb надо от владельца будущего сервера. На Debian с pg_createcluster тот же ключ можно передать после разделителя аргументов; перед повторным созданием существующего кластера сначала сохраните нужную конфигурацию и убедитесь, что удаляете только пустой целевой каталог, а не исходные данные.

# Вариант с прямым initdb: целевой кластер без checksums
sudo -u postgres /usr/lib/postgresql/18/bin/initdb \
  --no-data-checksums -D /srv/postgresql/18/main

# Вариант postgresql-common для нового кластера с другим именем
sudo pg_createcluster 18 upgrade -- --no-data-checksums

Есть и удобная двухэтапная схема: сначала выполнить pg_upgrade в целевой кластер без checksums, а затем выделить отдельное окно на pg_checksums уже версии 18. Это окно не обязательно будет коротким — утилите всё равно придётся просканировать и переписать блоки. Преимущество в другом: миграция основной версии и изменение формата страниц становятся двумя независимо проверяемыми операциями с отдельными точками возврата.

Самая дорогая ошибка — впервые запускать pg_checksums на боевом каталоге прямо в окне, не измерив время на копии. Прерывание не переключает конфигурацию наполовину: официальная документация говорит, что состояние checksums остаётся прежним и ту же операцию можно запустить заново. Но простой начнётся сначала, а причина аварийного прерывания может потребовать восстановления, поэтому проверенный бэкап всё равно обязателен.
pg_upgrade не идёт на PostgreSQL 18 из-за checksums: что менять и когда останавливать базы — схема
Схема к статье. Открыть схему в полном размере

Стенд: торговая компания «Северный склад», 40 РМ и два склада

Разберу практический проект целиком. Условный клиент — торговая компания «Северный склад», 40 РМ и два склада, учёт ведётся в 1С на PostgreSQL 16. Сервер работает на Debian 12, пакеты PostgreSQL получены из репозитория PGDG, каталог данных — /var/lib/postgresql/16/main, каталог конфигурации — /etc/postgresql/16/main. Боевая база занимает 640 ГБ, в сервере два процессора Xeon Silver, 128 ГБ оперативной памяти и зеркало из NVMe.

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

За восемь дней до работ я создал целевой кластер PostgreSQL 18 на отдельном порту и прогнал проверку при работающем PostgreSQL 16. Для Debian-подобной раскладки в pg_upgrade 18 параметры -d и -D указывают каталоги конфигурации; фактические каталоги данных берутся из параметра data_directory. Это отличается от команд pg_checksums и pg_controldata, которым нужен именно каталог данных.

sudo -u postgres /usr/lib/postgresql/18/bin/pg_upgrade \
  -b /usr/lib/postgresql/16/bin \
  -B /usr/lib/postgresql/18/bin \
  -d /etc/postgresql/16/main \
  -D /etc/postgresql/18/main \
  -p 5432 -P 5433 \
  --link --check

# Результат проверки:
# old cluster does not use data checksums but the new one does

Я указал --link уже на проверке, потому что именно этот режим был выбран для окна. Документация требует проверять режимы link, clone, copy-file-range и swap с соответствующим ключом: у каждого есть ограничения файловой системы. Простой запуск без ключа проверил бы дефолтный copy и мог не обнаружить, что жёсткие ссылки между выбранными каталогами невозможны.

Следующим шагом был замер не на production, а на восстановленной копии. На тестовой машине с сопоставимым NVMe команда pg_checksums версии 16 с --enable --progress обработала 640 ГБ за 21 минуту. В плане я заложил 35 минут, проверил место для снапшота и отдельно записал, что standby после смены checksums будет пересоздан с primary.

Фактический тайминг получился таким. В 00:05 завершили сеансы пользователей и остановили службы 1С. В 00:10 штатно остановили PostgreSQL 16, а в 00:12 проверили состояние shut down. С 00:12 до 00:33 работал pg_checksums. Затем контрольный запуск --check завершился без ошибок, а pg_controldata показал Data page checksum version: 1.

В 00:40 исходный PostgreSQL 16 подняли для короткого smoke-теста из 1С, затем снова корректно остановили и ещё раз убедились в состоянии shut down. Это второе выключение нельзя пропускать: боевой pg_upgrade требует остановленные исходный и целевой серверы. После этого pg_upgrade в режиме link с четырьмя заданиями занял около шести минут на данном стенде.

После запуска PostgreSQL 18 мы выполнили сгенерированные pg_upgrade скрипты, проверили расширения и восстановили настройки доступа. В PostgreSQL 18 pg_upgrade по умолчанию переносит большую часть оптимизаторной статистики, поэтому старый безусловный прогон analyze-in-stages по всей базе уже не является точной рекомендацией. Сначала мы собрали минимальную статистику только там, где её не хватало, затем обновили накопительную статистику для обслуживания.

sudo -u postgres /usr/lib/postgresql/18/bin/vacuumdb \
  --all --analyze-in-stages --missing-stats-only --jobs=4

sudo -u postgres /usr/lib/postgresql/18/bin/vacuumdb \
  --all --analyze-only --jobs=4

К 01:20 прикладной контур работал, обе складские точки прошли проверку документов и остатков. Реплику не пытались чинить поверх старого каталога: в воскресенье её пересоздали через pg_basebackup от нового primary. Цифры этого кейса показывают порядок операций, но не обещают таких же шести или двадцати одной минуты на другом железе.

Checksums включаются до pg_upgrade на исходном каталоге утилитой исходной основной версии — здесь PostgreSQL 16. Если вы сначала перенесли кластер без сумм, отдельное включение выполняется уже бинарным файлом PostgreSQL 18 по каталогу PostgreSQL 18. Не запускайте pg_checksums одной версии на каталоге другой.
Цифры и версии: Стенд: торговая компания «Северный склад», 40 РМ и два склада — схема
Цифры и версии: Стенд: торговая компания «Северный склад», 40 РМ и два склада. Открыть схему в полном размере

pg_checksums: правила прямой работы с файлами

У pg_checksums простой интерфейс: режимы --check, --enable и --disable. Но программа работает с файлами остановленного кластера напрямую, а включение переписывает блоки отношений на месте. Эти изменения не оформляются как обычная пользовательская транзакция и не распространяются на standby через WAL. Поэтому я отношусь к запуску как к операции над хранилищем, а не как к ещё одной административной SQL-команде.

Первое правило из документации однозначно: сервер должен быть корректно остановлен. Отсутствие процесса в списке недостаточно. Если в pg_controldata состояние не shut down, кластер сначала надо штатно поднять, дождаться окончания восстановления после сбоя и затем корректно остановить. Для standby возможен статус shut down in recovery, но процедуру для реплицируемого контура всё равно нужно планировать согласованно, а не обрабатывать узлы независимо наугад.

Второе правило: пока работает pg_checksums, ни сервер, ни другая программа не должны писать в каталог данных; документация прямо предупреждает о возможной потере данных. На Debian я останавливаю конкретный экземпляр systemd и проверяю его статус. Если кластером управляет Patroni, repmgr, Kubernetes-оператор или другой менеджер, сначала отключаю его автоматические действия штатным способом.

# Debian 12, кластер 16/main
sudo systemctl stop postgresql@16-main.service
sudo systemctl is-active postgresql@16-main.service

# Контрольное состояние каталога данных
sudo -u postgres /usr/lib/postgresql/16/bin/pg_controldata \
  -D /var/lib/postgresql/16/main | grep -Ei "cluster state|checksum"

# Включение и последующая полная проверка
sudo -u postgres /usr/lib/postgresql/16/bin/pg_checksums \
  --enable --progress -D /var/lib/postgresql/16/main
sudo -u postgres /usr/lib/postgresql/16/bin/pg_checksums \
  --check --progress -D /var/lib/postgresql/16/main

Ключ --progress, короткая форма -P, полезен при проверке и включении: без него большая база может долго не давать понятного человеку прогресса. Ключ --verbose, короткая форма -v, перечисляет проверяемые файлы и способен создать огромный лог, поэтому на большом production-кластере он редко полезен. Режим --check, короткая форма -c, является режимом по умолчанию, если другой режим не указан.

Ключ --no-sync, короткая форма -N, заставляет программу завершиться без ожидания безопасной записи всех файлов на диск. Документация называет его полезным для тестов и не рекомендует для production: сбой операционной системы после такого запуска способен оставить каталог повреждённым. В режиме --check этот ключ ничего не меняет. В PostgreSQL 18 также есть --sync-method; стандартное значение — fsync, а на Linux можно выбрать syncfs с оговорками из документации.

Отключение checksums происходит быстро, потому что --disable обновляет только файл pg_control; это не повод делать операцию без окна и резервной копии. Обратное включение снова потребует полного прохода. Если pg_checksums прервали или завершили сигналом во время включения либо отключения, конфигурация checksums остаётся прежней, и документация разрешает повторить ту же операцию. Это важное исправление распространённого мифа о том, что после прерывания обязательно остаётся безвозвратно смешанный кластер.

Повторный запуск не отменяет разбор причины. Если утилиту остановил оператор, можно устранить причину и снова выполнить тот же режим. Если были ошибки чтения, сбой контроллера или внезапная перезагрузка, сначала проверяют хранилище и решают, доверять ли каталогу. Я держу восстановленную резервную копию, а при наличии LVM или ZFS делаю согласованный снапшот остановленного набора томов, включающего PGDATA, WAL и все таблиспейсы.

Снапшот одного тома не является корректной точкой возврата, если WAL или таблиспейсы расположены на других томах и снимки сделаны в разные моменты. Кроме того, снапшот не заменяет независимый бэкап: он живёт на той же системе хранения и может погибнуть вместе с ней. Его роль в окне — быстрый локальный возврат, а не единственная копия данных.

Не останавливайте postgres низкоуровневой командой, оставляя systemd или оркестратор в состоянии, где он может снова запустить процесс. Сначала приостановите автоматику, затем остановите управляемый экземпляр штатно и непосредственно перед pg_checksums ещё раз проверьте статус службы, наличие процессов и состояние pg_controldata.

Реплики и pg_rewind: где появляется реальный риск

pg_checksums изменяет страницы непосредственно в файлах и не записывает эти изменения в WAL. Поэтому запуск только на primary не переключает настройку standby. Если ничего больше не сделать, узлы одного контура получают разное состояние checksums, а реплика не является эквивалентной заменой primary для последующего failover.

Официальная документация выделяет инструменты, которые напрямую копируют блоки файлов отношений, например pg_rewind. При несогласованном включении или отключении checksums такая копия может привести к страницам с неверными контрольными суммами. Рекомендованы два безопасных пути: остановить все кластеры и переключить их согласованно либо уничтожить standby, выполнить операцию на primary и создать standby заново.

В проектах с мажорным обновлением я обычно выбираю пересоздание. После pg_upgrade всё равно нужен standby новой основной версии, а pg_basebackup делает физическую копию уже согласованного нового primary. В документации pg_upgrade это прямо названо более простым решением для тех, кто не использует link-метод обновления standby, не хочет применять rsync или предпочитает пересоздать реплики.

Метод rsync из документации pg_upgrade предназначен для быстрого обновления standby после link-режима. Он использует точную команду с --archive --delete --hard-links --size-only --no-inc-recursive, запускается при остановленных серверах и требует одинаковой структуры каталогов. При наличии таблиспейсов аналогичную синхронизацию выполняют для каждого из них, а вынесенный pg_wal тоже обрабатывают отдельно.

Я не смешиваю этот метод с несогласованной сменой checksums. Если на primary уже переписали страницы, а старый standby не проходил ту же операцию, предпосылка идентичности содержимого стала сомнительной. Для торговой компании «Северный склад», 40 РМ и два склада мы выбрали новый pg_basebackup: это заняло больше календарного времени, зато процедура была понятной и проверяемой.

Перед остановкой асинхронной реплики надо проверить, что она получила и применила нужный WAL. Если планируется документированный rsync-путь pg_upgrade, руководство требует сравнить Latest checkpoint location в pg_controldata исходного primary и старых standby. Для обычной пересборки после запуска нового primary эта проверка всё равно полезна как подтверждение, что до отключения автоматики не было незамеченного отставания.

Если контуром управляет Patroni, пауза отключает автоматический failover, но не останавливает PostgreSQL сама по себе. Точный синтаксис зависит от имени кластера и расположения конфигурации; ключ --wait ждёт, пока паузу увидят все участники. После этого я проверяю список членов и только затем останавливаю службы на узлах согласно плану.

# Пример: имя Patroni-кластера warehouse
patronictl -c /etc/patroni/patroni.yml pause warehouse --wait
patronictl -c /etc/patroni/patroni.yml list warehouse

# После завершения всех работ и проверки репликации
patronictl -c /etc/patroni/patroni.yml resume warehouse --wait

У repmgr и операторов Kubernetes команды обслуживания другие; переносить синтаксис Patroni на них нельзя. Общий принцип один: автоматический failover, рестарт и самовосстановление должны быть предсказуемо отключены, а после работ — включены только после проверки primary, standby, replication slots и приложений.

После пересоздания standby я снова читаю Data page checksum version его собственным pg_controldata и сравниваю с primary. Затем проверяю потоковую репликацию, задержку воспроизведения и тест переключения по отдельному регламенту. Один зелёный статус streaming ещё не доказывает, что процедура возврата действительно работает.

Checksums — свойство всего физического кластера. В реплицируемой схеме не оставляйте узлы с разными настройками в роли взаимозаменяемых участников: либо меняйте все остановленные каталоги согласованно, либо пересоздавайте standby после операции на primary.

Мой чеклист окна обновления на PostgreSQL 18

Этот порядок я использую для схемы с одним primary, одной физической репликой и ночным окном. Количество рабочих мест почти не влияет на время файловых операций; важнее объём отношений, число файлов и таблиспейсов, производительность хранилища и выбранный режим pg_upgrade. Поэтому даже для 40 РМ нельзя брать чужой тайминг как расчёт.

За неделю до окна я фиксирую версии бинарных файлов, расширений и операционной системы, пути к данным и конфигурации, состояние checksums и выбранный режим переноса. Проверку запускаю именно бинарным файлом pg_upgrade новой версии. Исходный сервер при --check может работать, но целевой порт должен отличаться, а режим link, clone, copy-file-range или swap должен быть указан уже здесь.

За несколько дней восстанавливаю свежий бэкап, проверяю запуск приложения и измеряю pg_checksums на похожем диске. Одновременно оцениваю место: copy требует полноценного дополнительного объёма, clone зависит от поддержки reflink файловой системой, link и swap требуют размещения исходного и целевого каталогов на одной файловой системе. Для таблиспейсов ограничения и свободное место проверяю отдельно.

В день работ обновляю письменный план портов, служб и точек возврата. Для Debian это особенно важно: systemd-экземпляр, каталог конфигурации и каталог данных имеют похожие имена, но не взаимозаменяемы. Также сохраняю postgresql.conf, включаемые файлы, postgresql.auto.conf, pg_hba.conf, настройки расширений и описание replication slots.

После pg_upgrade читаю его предупреждения и выполняю созданные SQL-скрипты. PostgreSQL 18 переносит большую часть оптимизаторной статистики, если не задан --no-statistics, но не переносит всё: отдельно остаются расширенная статистика CREATE STATISTICS, данные расширений и накопительная статистика. Поэтому использую точные команды из раздела Statistics официального руководства, а не старый универсальный совет полностью анализировать базу до открытия доступа.

Мониторинг checksums тоже проверяю до сдачи окна. В pg_stat_database поле checksum_failures содержит накопленное число обнаруженных отказов по каждой базе либо NULL, если sums отключены; поле checksum_last_failure показывает время последнего события. Сам SQL ничего не лечит, зато позволяет убедиться, что сборщик мониторинга видит нужные значения и поднимет тревогу при их изменении.

SELECT datname, checksum_failures, checksum_last_failure
FROM pg_stat_database
ORDER BY datname NULLS FIRST;

На 8 сентября 2026 года актуальный выпуск ветки — PostgreSQL 18.6 от 13 августа 2026 года. Версия 18.5 не выпускалась: официальный changelog объясняет пропуск регрессией, найденной после подготовки релиза. Из этого не следует, что надо брать старую минорную версию. Выпуск 18.6 содержит исправления безопасности и отдельные указания по миграции, поэтому я ставлю актуальную минорную версию и заранее прохожу её release notes по используемым расширениям, индексам и логической репликации.

Не подменяйте rehearsal простой проверкой без режима переноса. Если боевой запуск будет с `--link`, `--clone`, `--copy-file-range` или `--swap`, тот же ключ должен присутствовать при pg_upgrade `--check`. Дефолтный режим — `--copy`.
Цифры и версии: Мой чеклист окна обновления на PostgreSQL 18 — схема
Цифры и версии: Мой чеклист окна обновления на PostgreSQL 18. Открыть схему в полном размере

Что checksums дают, а чего от них ждать нельзя

Документация осторожно говорит, что checksums могут дать небольшую потерю производительности, но не обещает универсальный процент. На знакомой мне нагрузке 1С у компаний с десятками рабочих мест измеримой пользователем разницы обычно нет, однако это наблюдение нельзя переносить на систему, которая постоянно упирается в IOPS. Для интенсивной записи я сравниваю задержки транзакций, объём WAL, загрузку дисков и контрольные операции приложения на одном и том же наборе данных.

Контрольная сумма хранится в странице данных, обновляется при записи страницы и проверяется при чтении. Она помогает обнаружить повреждение, которое иначе могло бы остаться незамеченным. Защищаются именно страницы данных; документация отдельно исключает внутренние структуры и временные файлы. WAL имеет собственные механизмы целостности и не становится объектом data checksums.

Checksums не ремонтируют страницу. При обычном обнаружении ошибки чтение завершается ошибкой, а счётчики статистики увеличиваются. Параметр ignore_checksum_failure существует для аварийного извлечения уцелевших данных, но документация предупреждает, что его применение может вызвать сбои, скрыть либо распространить повреждение. Это инструмент восстановления под контролем специалиста, а не настройка, которую включают ради продолжения работы.

Checksums также не заменяют ECC-память, резервное копирование и проверку восстановления. Если данные были логически испорчены приложением или сервер записал уже неверное содержимое с корректно вычисленной суммой, проверка страницы ничего не заметит. Я объясняю заказчику это как детектор части физических повреждений, а не как полную защиту базы.

При выборе режима pg_upgrade план возврата различается. В copy старые файлы не меняются. Clone использует поддерживаемое файловой системой клонирование блоков и оставляет старый кластер нетронутым. Copy-file-range по условиям документации также не относится к разрушительным режимам для старого кластера, хотя скорость и фактическое совместное использование физических блоков зависят от файловой системы.

В link старые и новые каталоги используют жёсткие ссылки. Если перенос завершён, но новый кластер ещё не запускался, pg_upgrade описывает возврат: у старого global/pg_control убирают суффикс .old. После первого запуска нового кластера общие файлы уже могли измениться, и запуск старого становится небезопасным — нужен бэкап. Поэтому фраза «при link отката нет» слишком груба: точная граница проходит по запуску нового сервера.

Swap ещё жёстче: после момента, когда pg_upgrade сообщает о разрушительном изменении исходного кластера, тот уже нельзя безопасно запускать. Документация также рекомендует для swap метод синхронизации fsync, потому что этот режим создаёт много ненужных файлов в старом каталоге и syncfs может затянуть финальную синхронизацию. Без отрепетированного восстановления я не выбираю swap для первой миграции.

Само сообщение о несовпадении checksums не означает повреждение. При --check данные не меняются, а при обычном запуске сравнение контрольных данных происходит до переноса пользовательских файлов. Потерять здесь можно окно, но не каталог. Именно поэтому ранний pg_upgrade --check даёт так много пользы при почти нулевом риске.

Если времени мало, совместимый целевой кластер PostgreSQL 18 с --no-data-checksums лучше импровизации над production. Но я сразу создаю отдельную задачу с владельцем и датой: остановить новый кластер, включить sums его pg_checksums, согласованно обработать реплики и включить мониторинг. Временное решение без срока быстро становится постоянной архитектурой.

Выбирайте режим переноса по проверенному плану возврата. Для copy, clone и copy-file-range старый кластер остаётся нетронутым; для link он безопасен только до запуска нового сервера; для swap границу необратимости сообщает сама утилита.

Частые вопросы

Обязательно ли включать контрольные суммы при переходе на PostgreSQL 18?

Нет. Новый дефолт относится к кластерам, создаваемым initdb версии 18. pg_upgrade требует совпадения, поэтому целевой кластер можно создать с `--no-data-checksums` и сохранить состояние исходного. Позже sums включаются отдельной офлайн-операцией pg_checksums уже на новом кластере.

Сколько времени занимает pg_checksums --enable?

Официального норматива нет. Утилита проходит файлы отношений и при включении переписывает блоки с изменившейся суммой, поэтому время зависит от объёма и хранилища. В описанном кейсе 640 ГБ на NVMe заняли 21 минуту, а другой стенд с 800 ГБ на SATA RAID10 — 2 часа 40 минут. Корректный прогноз даёт только замер на восстановленной копии.

Можно ли включить checksums на работающей базе?

Нет. pg_checksums требует корректно остановленный сервер, а во время операции никакая другая программа не должна писать в каталог. Проверяйте состояние через pg_controldata и отключайте автоматический рестарт или failover до запуска утилиты.

Что будет, если pg_checksums прервать?

По официальной документации конфигурация data checksums останется прежней, а ту же операцию можно запустить заново. Это не делает прерывание безобидным: потеряется время, а при сбое диска или питания сначала надо проверить хранилище и при необходимости восстановиться из проверенной копии.

Что делать с физической репликой после изменения checksums на primary?

Безопасны два официальных пути: остановить все узлы и изменить их согласованно либо удалить standby, выполнить операцию на primary и пересоздать standby. Для мажорного обновления я чаще выбираю новый pg_basebackup от уже запущенного PostgreSQL 18. Несогласованная конфигурация особенно опасна при pg_rewind и других инструментах прямого копирования блоков.

Как заранее понять, возникнет ли ошибка pg_upgrade?

Выполните pg_upgrade `--check` бинарным файлом PostgreSQL 18 и сравните `Data page checksum version` в pg_controldata обоих каталогов. При работающем исходном сервере задайте разные порты. Для link, clone, copy-file-range или swap обязательно укажите тот же режим уже при проверке.

Нужно ли после pg_upgrade 18 полностью анализировать всю базу?

PostgreSQL 18 по умолчанию переносит большую часть оптимизаторной статистики. Руководство рекомендует сначала vacuumdb `--all --analyze-in-stages --missing-stats-only`, затем vacuumdb `--all --analyze-only`; число параллельных заданий задаётся `--jobs`. Выполните и все дополнительные скрипты, которые создаст pg_upgrade.

Можно ли откатиться после pg_upgrade?

В copy, clone и copy-file-range старый кластер не изменяется. В link его можно вернуть до запуска нового сервера, восстановив имя `global/pg_control` по инструкции pg_upgrade; после запуска нового это небезопасно. В swap после отмеченного утилитой разрушительного этапа нужен возврат из резервной копии.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи