52.12. pg_locks#
52.12. pg_locks
Представление pg_locks
предоставляет доступ к информации о блокировках, удерживаемых активными процессами внутри сервера базы данных. См. Глава 13 для более подробного обсуждения блокировок.
pg_locks
содержит одну строку для каждого активного объекта, который может быть заблокирован, запрошенного режима блокировки и соответствующего процесса. Таким образом, один и тот же объект может появляться множество раз, если на него наложены или ожидаются блокировки несколькими процессами. Однако объект, на котором в данный момент нет блокировок, вообще не будет отображаться.
Существует несколько различных типов объектов, которые можно блокировать:
целые отношения (например, таблицы), отдельные страницы отношений,
отдельные кортежи отношений,
идентификаторы транзакций (как виртуальные, так и постоянные),
и общие объекты базы данных (идентифицируемые классом OID и объектом OID,
так же, как в pg_description
или
pg_depend
). Кроме того, право на расширение
отношения представлено в виде отдельного объекта, так же как и право на
обновление pg_database
.datfrozenxid
.
Также, на числа с пользовательскими значениями можно установить “рекомендательные” блокировки.
Таблица 52.12. pg_locks
Колонки
Тип столбца Описание |
---|
Тип блокируемого объекта:
|
OID базы данных, в которой существует цель блокировки, или ноль, если цель является общим объектом, или null, если цель является идентификатором транзакции |
OID отношения, на которое нацелена блокировка, или null, если цель не является отношением или частью отношения |
Номер страницы, на которую нацелена блокировка внутри отношения, или null, если целью не является страница отношения или кортеж |
Номер кортежа, на который нацелена блокировка внутри страницы, или null, если целью не является кортеж |
Виртуальный идентификатор транзакции, на которую нацелена блокировка, или null, если целью не является виртуальный идентификатор транзакции |
ID транзакции, на которую нацелена блокировка, или null, если целью не является идентификатор транзакции |
OID системного каталога, содержащего цель блокировки, или null, если цель не является общим объектом базы данных |
OID цели блокировки в ее системном каталоге или null, если цель не является общим объектом базы данных |
Номер столбца, на который нацелена блокировка (теги |
Виртуальный идентификатор транзакции, который удерживает или ожидает эту блокировку |
Идентификатор процесса сервера, удерживающего или ожидающего эту блокировку, или null, если блокировка удерживается подготовленной транзакцией |
Имя режима блокировки, удерживаемого или желаемого этим процессом (см. Раздел 13.3.1 и Раздел 13.2.3) |
True, если блокировка удерживается, false, если ожидается блокировка |
True, если блокировка была получена через быстрый путь, false, если была получена через основную таблицу блокировок |
Время, когда процесс сервера начал ожидать этой блокировки,
или null, если блокировка удерживается.
Обратите внимание, что это может быть null в течение очень короткого периода времени после начала ожидания, даже если |
granted
в значении true в строке, представляющей блокировку, означает, что указанный процесс владеет этой блокировкой. Значение false указывает на то, что этот процесс в настоящее время ожидает получения этой блокировки, что подразумевает, что по крайней мере один другой процесс владеет или ожидает конфликтующий режим блокировки на том же объекте блокировки. Ожидающий процесс будет спать, пока другая блокировка не будет освобождена (или не будет обнаружена ситуация взаимной блокировки). Один процесс может ожидать получения не более одной блокировки одновременно.
Во время выполнения транзакции процесс сервера удерживает исключающую блокировку на виртуальный идентификатор транзакции. Если транзакции назначается постоянный идентификатор (что обычно происходит только в случае изменения состояния базы данных), она также удерживает исключающую блокировку на постоянный идентификатор транзакции до ее завершения. Когда процессу необходимо ожидать завершения другой транзакции, он пытается получить разделяемую блокировку на идентификатор другой транзакции (виртуальный или постоянный, в зависимости от ситуации). Это удастся только тогда, когда другая транзакция завершится и освободит свои блокировки.
Хотя кортежи являются типом объекта, который можно блокировать, информация о блокировках на уровне строк хранится на диске, а не в памяти, и поэтому обычно блокировки на уровне строк не отображаются в этом представлении. Если процесс ожидает блокировки на уровне строки, он обычно отображается в представлении как ожидающий постоянного идентификатора транзакции текущего владельца этой блокировки строки.
Рекомендательные блокировки могут быть получены на ключах, состоящих из одного значения типа bigint
или двух целочисленных значений.
Ключ типа bigint
отображается с его старшей половиной в столбце classid
, его младшей половиной в столбце objid
, и objsubid
равным 1. Исходное значение типа bigint
может быть восстановлено с помощью выражения (classid::bigint << 32) | objid::bigint
. Целочисленные ключи отображаются с первым ключом в столбце classid
, вторым ключом в столбце objid
, и objsubid
равным 2. Фактическое значение ключей зависит от пользователя. Рекомендательные блокировки локальны для каждой базы данных, поэтому столбец database
имеет значение для рекомендательной блокировки.
pg_locks
предоставляет общий вид всех блокировок в кластере базы данных, а не только тех, которые относятся к текущей базе данных. Хотя столбец relation
может быть объединен с pg_class
.oid
для идентификации заблокированных отношений, это будет работать правильно только для отношений в текущей базе данных (те, для которых столбец database
является либо OID текущей базы данных, либо нулем).
Колонку pid
можно объединить с колонкой pid
представления pg_stat_activity
, чтобы получить дополнительную информацию о сессии, удерживающем или ожидающем каждую блокировку, например.
SELECT * FROM pg_locks pl LEFT JOIN pg_stat_activity psa ON pl.pid = psa.pid;
Также, если вы используете подготовленные транзакции, столбец virtualtransaction
можно объединить со столбцом transaction
представления pg_prepared_xacts
, чтобы получить больше информации о подготовленных транзакциях, удерживающих блокировки. (Подготовленная транзакция никогда не будет ожидать блокировку, но она продолжает удерживать блокировки, которые получила во время выполнения). Например:
SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx ON pl.virtualtransaction = '-1/' || ppx.transaction;
Возможно получить информацию о том, какие процессы блокируют другие процессы, объединяя pg_locks
сам с собой, но это очень сложно сделать правильно в деталях. Такой запрос должен был бы закодировать знание о том, какие режимы блокировки конфликтуют друг с другом. Что хуже, представление pg_locks
не раскрывает информацию о том, какие процессы находятся впереди других в очередях ожидания блокировки, а также информацию о том, какие процессы являются параллельными рабочими процессами, работающими от имени других клиентских сессий. Лучше использовать функцию pg_blocking_pids()
(см. Таблица 9.66) для определения, за какими процессами заблокирован ожидающий процесс.
Представление pg_locks
отображает данные как из обычного менеджера блокировок, так и из менеджера предикатных блокировок, которые являются отдельными системами; кроме того, обычный менеджер блокировок разделяет свои блокировки на обычные и быстрые блокировки.
Эти данные не гарантируют полной согласованности.
При запросе представления, данные о быстрых блокировках (с fastpath
= true
) собираются из каждого бэкенда по очереди, без замораживания состояния всего менеджера блокировок, поэтому возможно, что блокировки будут захвачены или освобождены во время сбора информации. Однако следует отметить, что эти блокировки не конфликтуют с другими блокировками, находящимися в данный момент. После того, как все бэкенды были опрошены на предмет быстрых блокировок, остаток обычного менеджера блокировок блокируется как единое целое, и собирается согласованная снимок всех оставшихся блокировок в виде атомарного действия. После разблокировки обычного менеджера блокировок, аналогично блокируется менеджер предикатных блокировок, и все предикатные блокировки собираются как атомарное действие. Таким образом, за исключением быстрых блокировок, каждый менеджер блокировок будет предоставлять согласованный набор результатов, но поскольку мы не блокируем оба менеджера блокировок одновременно, возможно, что блокировки будут захвачены или освобождены после опроса обычного менеджера блокировок и до опроса менеджера предикатных блокировок.
Блокировка обычного и/или предикатного менеджера блокировок может оказать некоторое влияние на производительность базы данных, если этот вид часто используется. Блокировки удерживаются только в течение минимально необходимого времени для получения данных из менеджеров блокировок, но это не исключает возможности влияния на производительность.