Найти в Дзене
Postgres DBA

VMSTAT : Корреляция и причинно-следственная связь роста CS и снижения производительности СУБД PostgreSQL

С каким типом ожиданий СУБД PostgreSQL может коррелировать рост значений cs/vmstat ? И может ли данная корреляция быть одной из причин снижения производительности СУБД ? Отличный вопрос, который затрагивает важный аспект диагностики производительности PostgreSQL. Рост значения cs (context switches) в утилите vmstat действительно часто коррелирует с определенными типами ожиданий (wait events) в PostgreSQL и почти всегда указывает на причину снижения производительности. Высокое количество переключений контекста (cs) указывает на то, что операционная система активно переключается между выполнением разных процессов и потоков. В контексте PostgreSQL это обычно коррелирует с ожиданиями двух основных типов: Высокое количество переключений контекста (cs) само по себе является причиной снижения производительности. Вот почему: Рост cs/vmstat сильно коррелирует с ожиданиями блокировок (LWLock и heavyweight locks) в PostgreSQL. Эта корреляция не просто совпадение, а прямое указание на то, что сниж
Оглавление
СУБД это система связынных и влияющих друг на друго компонент.
СУБД это система связынных и влияющих друг на друго компонент.

Вопрос

С каким типом ожиданий СУБД PostgreSQL может коррелировать рост значений cs/vmstat ? И может ли данная корреляция быть одной из причин снижения производительности СУБД ?

Ответ

Отличный вопрос, который затрагивает важный аспект диагностики производительности PostgreSQL. Рост значения cs (context switches) в утилите vmstat действительно часто коррелирует с определенными типами ожиданий (wait events) в PostgreSQL и почти всегда указывает на причину снижения производительности.

С какими типами ожиданий PostgreSQL коррелирует рост cs?

Высокое количество переключений контекста (cs) указывает на то, что операционная система активно переключается между выполнением разных процессов и потоков. В контексте PostgreSQL это обычно коррелирует с ожиданиями двух основных типов:

1. Ожидания, связанные с блокировками (Lock Waits):
Это самая прямая и частая корреляция.

  • LWLock (Lightweight Lock): Это короткие и частые блокировки, используемые PostgreSQL для защиты внутренних структур данных в разделяемой памяти.
    Конкретные ожидания: buffer_content, lock_manager, shared_buffer, wal_insert, buffer_mapping, client_connection и др.
    Почему корреляция: Когда множество сеансов пытаются получить эксклюзивный доступ к одной и той же структуре данных (например, к одной странице буфера в памяти или к точке вставки в WAL), они будут заблокированы. ОС приостанавливает их выполнение (переводит в состояние сна) и переключает контекст на другие выполняемые процессы. Это приводит к резкому росту cs.
  • Тяжелые блокировки (Heavyweight Locks): Блокировки на уровне SQL, такие как RowExclusiveLock, ShareLock, ExclusiveLock и особенно AccessExclusiveLock.
    Конкретные ожидания: lock, transactionid.
    Почему корреляция: Если длительная транзакция удерживает AccessExclusiveLock на таблице (например, во время выполнения ALTER TABLE), все другие запросы к этой таблице будут ждать. ОС будет вынуждена переключать контекст с этих ждущих сеансов на другие, увеличивая cs.

2. Ожидания, связанные с вводом-выводом (I/O Waits):
Корреляция здесь менее прямая, но все же есть.

  • Конкретные ожидания: DataFileRead, DataFileWrite, WALWrite, SyncRep.
    Почему корреляция: Когда процесс PostgreSQL отправляет запрос на чтение/запись на диск, он добровольно отдает управление (добровольное переключение контекста - voluntary cs), пока ждет ответа от подсистемы I/O. Если диск медленный и множество процессов одновременно ждут его ответа, это внесет вклад в общее количество cs. Однако в этом случае рост cs будет следствием проблемы (медленного I/O), а не ее причиной.

Может ли данная корреляция быть причиной снижения производительности?

Да, и это не просто корреляция, а прямая причинно-следственная связь.

Высокое количество переключений контекста (cs) само по себе является причиной снижения производительности. Вот почему:

  1. Накладные расходы ЦП: Каждое переключение контекста — это дорогостоящая операция для процессора. Ядро ОС должно сохранить состояние регистров, стек и другие структуры данных текущего исполняемого процесса, загрузить состояние нового процесса и передать ему управление. Циклы процессора, которые могли бы тратиться на полезную работу (выполнение запросов), тратятся на организацию этой очереди.
  2. Потеря локальности данных (Cache Thrashing): При переключении контекста процессор теряет данные, которые он кэшировал для предыдущего процесса (кэш L1/L2, TLB - буфер ассоциативной трансляции). Когда этот процесс будет запущен снова, ему придется заполнять кэш заново, что приводит к простоям процессора и увеличению времени выполнения.
  3. Признак конкуренции: Высокий cs — это в первую очередь симптом. Он говорит о том, что множество процессов активно конкурируют за какие-то ресурсы (память, блокировки, CPU). Эта конкуренция и является корневой причиной падения производительности. Процессы не продвигаются в своей работе, а вместо этого постоянно "толкаются" в очереди.

Вывод:

Рост cs/vmstat сильно коррелирует с ожиданиями блокировок (LWLock и heavyweight locks) в PostgreSQL. Эта корреляция не просто совпадение, а прямое указание на то, что снижение производительности вызвано конкуренцией за ресурсы и высокими накладными расходами ОС на переключение между задачами, которые не могут продвинуться из-за этой конкуренции.

Причинно-следственный анализ

Всё в этом мире взаимосвязанно.
Всё в этом мире взаимосвязанно.

Вопрос

Какое событие первично - рост ожиданий СУБД PostgreSQL или рост количества cs/vmstat ?

Ответ

Отличный и очень глубокий вопрос. Ответ на него заключается в понимании иерархии причинно-следственных связей между планировщиком операционной системы и механизмами работы СУБД.

В абсолютном большинстве случаев первичным является рост ожиданий (wait events) внутри PostgreSQL. Рост переключений контекста (cs) — это вторичное следствие, механизм, с помощью которого ОС реагирует на эти ожидания.

Можно представить эту цепочку так:

Первопричина (в СУБД) -> Ожидание (wait event) -> Реакция ОС -> Рост cs

Почему ожидания в PostgreSQL первичны?

  1. Процесс инициирует ожидание: Сеанс PostgreSQL в процессе выполнения запроса достигает точки, где он не может продолжить работу без какого-то ресурса.
    Пример 1: Ему нужна страница данных с диска. Он инициирует операцию I/O и добровольно переходит в состояние сна (sleep), ожидая её завершения. Это регистрируется как wait event DataFileRead.
    Пример 2: Он пытается изменить строку, но другая транзакция удерживает на ней блокировку. Сеанс вынужденно переходит в состояние сна, ожидая освобождения блокировки. Это регистрируется как wait event lock.
  2. Реакция планировщика задач ОС: Когда процесс PostgreSQL переходит в состояние сна (добровольно или вынужденно), он отдает свой квант времени процессора. Планировщик задач ОС фиксирует это и производит переключение контекста (cs), чтобы отдать освободившееся процессорное время другому готовому к выполнению процессу (например, другому сеансу БД или процессу самой ОС).
  3. Результат: Таким образом, каждое ожидание внутри PostgreSQL (кроме ожидания CPU) приводит к тому, что процесс будет "усыплен", и ОС будет вынуждена выполнить переключение контекста, чтобы не простаивать. Чем больше сеансов одновременно находятся в состоянии ожидания, тем чаще ОС приходится переключаться между ними и другими процессами — рост cs.

Возможна ли обратная ситуация?

Теоретически, да, но на практике это нетипичная для PostgreSQL ситуация.

  • Гипотетический сценарий: Представим, что на сервере запущен какой-то очень агрессивный процесс (не PostgreSQL), который постоянно исчерпывает свой квант времени и активно вытесняется планировщиком ОС (высокий cs из-за этого процесса). Это создает нагрузку на планировщик и процессор.
  • Влияние на PostgreSQL: В этой ситуации рабочие процессы PostgreSQL будут чаще и дольше ждать своего кванта CPU. В pg_stat_activity их состояние будет active, а wait event — CPU (если track_activities включен), но при этом сам запрос будет выполняться медленнее из-за нехватки процессорного времени.
  • Итог: В этом случае первичен внешний по отношению к СУБД рост cs, который приводит к вторичной проблеме — нехватке CPU для процессов PostgreSQL, что регистрируется как ожидание типа CPU.

Однако этот сценарий:

  1. Встречается гораздо реже.
  2. Легко диагностируется: высокий us (user CPU) в vmstat/top при низком id (idle), при этом основные wait events в PostgreSQL будут CPU, а не I/O или locks.

Ключевое различие: Добровольные vs. Принудительные переключения контекста

  • Добровольные (voluntary, nvcsw в pidstat): Процесс сам отдает управление, когда ему нужно ждать (I/O, блокировка). Это следствие ожиданий в СУБД.
  • Принудительные (non voluntary, nivcsw): Планировщик ОС принудительно забирает управление у процесса, потому что он исчерпал свой квант времени или появился процесс с higher priority. Высокий уровень принудительных переключений может указывать на конкуренцию за CPU.

Для PostgreSQL высокий cs почти всегда связан с ростом именно добровольных переключений.

Первичное событие : Ожидание в PostgreSQL (I/O, Lock)

Механизм: Процесс СУБД переходит в сон, ОС переключает контекст на другой процесс

Вторичное событие: Рост cs в vmstat

Следствие: Снижение производительности из-за накладных расходов на переключения

Первичное событие :Рост cs из-за внешней нагрузки (другой софт)

Механизм: ОС не может вовремя дать CPU процессам СУБД

Вторичное событие: Ожидание CPU в PostgreSQL

Следствие: Снижение производительности из-за нехватки вычислительных ресурсов

Вывод: В 99% случаев проблем с PostgreSQL первичны именно ожидания внутри СУБД (Locks, I/O). Резкий рост cs в vmstat — это важнейший сигнал и индикатор этих ожиданий на уровне операционной системы, который говорит о том, что процессы не работают, а ждут, и ОС тратит силы на переключения между ними. Поэтому при росте cs нужно сразу смотреть вглубь — на анализ wait events .