Параметры io_*, которые мы рассматривали до сих пор, описывают сами запросы ввода-вывода: насколько велик каждый из них, сколько процесс может держать в полёте. Эти два решают, кто фактически их выполняет. Я писал об архитектуре и о том, что PostgreSQL 19 с ней делает, в статье AIO Grows Up; здесь — взгляд на уровне параметров, и он включает исправление того, что я там сказал.
effective_io_concurrency — это запрос. io_max_concurrency — это удовлетворение.
Новый в PostgreSQL 18 как часть подсистемы асинхронного ввода-вывода, io_max_concurrency представляет собой жёсткий потолок того, сколько операций ввода-вывода один процесс может иметь в полёте одновременно. Не на весь кластер; на процесс. Контекст — postmaster, поэтому для изменения требуется перезапуск, а значение по умолчанию — -1, что указывает PostgreSQL выбрать значение при запуске. Диапазон простирается до 1024.
«База данных зависла». Мы слышали ту или иную версию этого предложения не раз за прошедшую неделю, от одной и той же команды, по поводу того, что выглядело как одна и та же проблема. Это была не одна и та же проблема. Однажды Postgres действительно перестал отвечать. Все остальные разы Postgres был в порядке, а соединение, находившееся в пуле приложения, тихо умерло где-то между приложением и базой данных.
Обе неисправности приводят к одному и тому же вызову в 2 часа ночи: приложение не может связаться с базой данных. Только одна из них означает, что база данных действительно в беде. Путаница между ними стоит вам самого дорогого ресурса в инциденте — первых десяти минут, когда вы ещё решаете, с каким типом проблемы имеете дело.
Истинное зависание PostgreSQL означает, что сам сервер перестал отвечать на уровне операционной системы. Вы не можете открыть новую сессию к нему, ни с какого клиента, ниоткуда. Проблема устаревшего соединения означает, что Postgres здоров и доступен. Проблема в конкретном соединении, уже находящемся в пуле вашего приложения, которое указывает на сокет, умерший где-то по пути, обычно без того, чтобы какая-либо из сторон получила чистый сигнал о том, что это произошло.
Теперь мы вступаем во владения io_* — самую новую в пространстве имён GUC: ничего из этого не существовало до PostgreSQL 17. Если effective_io_concurrency отвечает на вопрос «сколько операций ввода-вывода мы держим в полёте?», то io_combine_limit отвечает на ортогональный вопрос: «какова величина каждой из них?» Глубина и ширина.
Автор Christophe Pettus: https://thebuild.com/blog/all-your-gucs-in-a-row-intervalstyle/
IntervalStyle — младший «брат» DateStyle, и он унаследовал семейную черту: он выглядит как предпочтение форматирования вывода, но также меняет то, как PostgreSQL разбирает ваш ввод. Мы рассматривали версию даты этого трюка в статье про DateStyle. Версия для интервалов менее известна и в одном конкретном случае более неприятна.
Когда вы работаете с базой данных, то часто выполняете несколько запросов, которые связаны друг с другом. Например, перемещение денег с одного счета на другой.
Каждое соединение, которое кто-либо устанавливал с сервером PostgreSQL начиная с версии 8.0, открывалось с того, что сервер без приглашения объявлял значение integer_datetimes. Начиная с PostgreSQL 10 объявляемое значение — это единственное значение, с которым вообще может быть собран сервер PostgreSQL, и текущая документация отделывается от всей темы одним предложением: «Начиная с PostgreSQL 10 это всегда on». Так что это пост о том, почему параметр ровно с одним возможным значением всё ещё представляется каждому клиенту в начале каждого разговора.
in_hot_standby — это лампочка, а не переключатель. Он сообщает, является ли сервер, к которому вы подключены, в данный момент горячим резервом: включён, когда ваша сессия работает на реплике, которая воспроизводит WAL и принимает запросы только для чтения (состояние, которое включает hot_standby), выключен на первичном сервере. Это логический параметр, он появился в PostgreSQL 14, и его контекст — ни один из обычных четырёх, потому что никто не может его изменить:
postgres=# SET in_hot_standby = off;
ERROR: parameter "in_hot_standby" cannot be changed
postgres=# ALTER SYSTEM SET in_hot_standby = off;
ERROR: parameter "in_hot_standby" cannot be changed
ignore_system_indexes завершает череду из трёх последовательных параметров с именем ignore_-что-то и с удобным отрывом является самым вежливым в этом семействе. ignore_checksum_failure и ignore_invalid_pages говорят PostgreSQL продолжать, несмотря на доказательства повреждения; этот же просто говорит ему перестать доверять набору путей доступа. Это логический параметр, по умолчанию выключен, и он живёт в редком контексте backend: его можно установить только до того, как сессия существует, либо в postgresql.conf (влияя только на новые сессии), либо во время подключения, что удобнее всего сделать как PGOPTIONS="-P", эквивалентный серверный переключатель. Установите его после подключения — и получите ошибку. Во всех поддерживаемых версиях это один из ровно двух параметров с таким контекстом (другой — post_auth_delay), он классифицирован как параметр разработчика и не появляется в образце файла конфигурации. Всё это — способ сервера сказать: вы не должны были это находить.
Никто не находит ignore_invalid_pages, читая документацию от корки до корки. Вы находите его, вставив PANIC: WAL contains references to invalid pages в поисковую систему, обычно в час, когда вы предпочли бы спать. Это параметр разработчика, отсутствующий в postgresql.conf.sample, присутствующий начиная с PostgreSQL 13. По умолчанию он выключен, а контекст — postmaster, что на этот раз ничего не стоит: сервер, который вам нужно было бы перезапустить, уже не работает.
Первая нормальная форма (1NF) является самым известным правилом в нормализации базы данных. Оно требует, чтобы таблицы не содержали повторяющихся групп и каждый столбец содержал атомарные значения. Но в реальных системах баз данных разработчики часто намеренно нарушают это правило при моделировании сложных данных. Давайте выясним почему.
ignore_checksum_failure — это не столько параметр конфигурации, сколько ломик в витрине за стеклом. По умолчанию он выключен, он вообще не появляется в postgresql.conf.sample (образец файла вежливо отказывается его рекламировать), и документация помещает его в раздел «Параметры разработчика», рядом с другими инструментами, которые вы надеетесь никогда не будете держать в руках. Контекст — суперпользователь, что означает, что суперпользователь (или роль, которой было предоставлено право SET на него, а такой роли не должно существовать) может переключить его в живой сессии командой SET; без перезагрузки, без перезапуска. Именно такая гранулярность и требуется для его единственного законного применения. Он появился в PostgreSQL 9.3 вместе с самими контрольными суммами данных: функция, которая проверяет, и рычаг, который отменяет проверку, родились вместе.
idle_session_timeout — это уборка, а не защита. Его «собрат», idle_in_transaction_session_timeout, защищает базу данных от реального вреда: простаивающая транзакция удерживает блокировки и фиксирует горизонт xmin, и vacuum от этого страдает. Сессия, простаивающая вне транзакции, ничего из этого не делает. Она занимает слот соединения, фоновый процесс и немного памяти. Вот и весь счёт, и этот параметр существует, чтобы его выставить. В документации сказано то же самое, отмечая, что простаивающая сессия без транзакции не создаёт больших затрат, поэтому необходимости в этом таймауте меньше, чем в его «собрате».