×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

2.10.3. Метод явного блокирования

2.10.3.1. Блокировки уровня таблицы
2.10.3.2. Блокировки на уровне строк
2.10.3.3. Блокировки на уровне страниц
2.10.3.4. Взаимные блокировки
2.10.3.5. Рекомендательные блокировки

Digital Q.DataBase предоставляет различные режимы блокировок для управления одновременным доступом к данным в таблицах. Данные режимы могут применяться для управления блокировками на уровне приложения в ситуациях, когда MVCC не обеспечивает требуемого поведения. Кроме того, большинство Digital Q.DataBase команд автоматически запрашивают блокировки в соответствующих режимах, чтобы гарантировать, что связанные таблицы не будут удалены или изменены несовместимым образом во время выполнения команды. (Например, команда TRUNCATE не может быть безопасно выполнена одновременно с другими операциями над той же таблицей, поэтому она запрашивает ACCESS EXCLUSIVE блокировку таблицы для обеспечения этого условия.)

Для просмотра списка всех текущих активных блокировок на сервере базы данных используйте pg_locks системное представление. Для получения дополнительной информации о мониторинге состояния подсистемы диспетчера блокировок обратитесь к разделу Глава 3.12.

2.10.3.1. Блокировки уровня таблицы #

В представленном ниже списке перечислены доступные режимы блокировок и контексты, в которых они автоматически используются компонентом Digital Q.DataBase. Любую из этих блокировок также можно получить явно с помощью команды LOCK. Следует учитывать, что все эти режимы блокировок являются блокировками уровня таблицы, даже если в их названии содержится слово «строка»; названия режимов блокировок являются исторически сложившимися. В некоторой степени эти названия отражают типичное использование каждого режима — однако их семантика идентична. Единственное реальное различие между одним режимом блокировки и другим заключается в наборе режимов блокировок, с которыми каждый из них конфликтует (см. Таблица 2.10.2). Две транзакции не могут одновременно удерживать блокировки конфликтующих режимов на одной таблице. (При этом транзакция никогда не конфликтует сама с собой. Например, она может сначала получить ACCESS EXCLUSIVE блокировку, а затем — ACCESS SHARE блокировка той же таблицы.) Неконфликтующие режимы блокировок могут удерживаться одновременно множеством транзакций. Следует отметить, что некоторые режимы блокировок являются самоконфликтующими (например, ACCESS EXCLUSIVE блокировка не может удерживаться более чем одной транзакцией одновременно), в то время как другие не являются самоконфликтующими (например, ACCESS SHARE блокировка может удерживаться несколькими транзакциями).

Режимы блокировок уровня таблицы

ACCESS SHARE (AccessShareLock)

Конфликтует с ACCESS EXCLUSIVE блокировка только этим режимом.

Команда SELECT захватывает блокировку в данном режиме для задействованных таблиц. В целом, любой запрос, который только читает таблицу и не изменяет её, будет запрашивать этот режим блокировки.

ROW SHARE (RowShareLock)

Конфликтует с EXCLUSIVE и ACCESS EXCLUSIVE режимы блокировок.

Команда SELECT команда запрашивает блокировку в данном режиме для всех таблиц, для которых указан один из FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE, или FOR KEY SHARE параметров (в дополнение к ACCESS SHARE блокировкам любых других таблиц, обращение к которым выполняется без явного указания FOR ... параметра блокировки).

ROW EXCLUSIVE (RowExclusiveLock)

Конфликтует с SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE режимы блокировок.

Команды UPDATE, DELETE, INSERT, и MERGE запрашивают данный режим блокировки для целевой таблицы (в дополнение к ACCESS SHARE блокировкам всех остальных задействованных таблиц). Как правило, данный режим блокировки запрашивается любой командой, которая изменяет данные в таблице.

SHARE UPDATE EXCLUSIVE (ShareUpdateExclusiveLock)

Конфликтует с SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE режимы блокировок. Данный режим защищает таблицу от одновременных изменений схемы и VACUUM выполнения.

Блокировка запрашивается командами VACUUM (без FULL), ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, и некоторые ALTER INDEX и ALTER TABLE варианты (подробные сведения см. в документации по данным командам).

SHARE (ShareLock)

Конфликтует с ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE режимы блокировок. Данный режим защищает таблицу от одновременного изменения данных.

Блокировка запрашивается командами CREATE INDEX (без CONCURRENTLY).

SHARE ROW EXCLUSIVE (ShareRowExclusiveLock)

Конфликтует с ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE режимы блокировок. Данный режим защищает таблицу от одновременного изменения данных, а также является самоисключающим, поэтому в каждый момент времени его может удерживать только один сеанс.

Блокировка запрашивается командами CREATE TRIGGER а также некоторые формы ALTER TABLE.

EXCLUSIVE (ExclusiveLock)

Конфликтует с ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE режимы блокировок. Данный режим допускает только одновременные ACCESS SHARE блокировки, то есть параллельно с транзакцией, удерживающей данный режим блокировки, могут выполняться только операции чтения из таблицы. транзакция, удерживающая данный режим блокировки.

Блокировка запрашивается командами REFRESH MATERIALIZED VIEW CONCURRENTLY.

ACCESS EXCLUSIVE (AccessExclusiveLock)

Конфликтует с режимами блокировки всех типов (ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, и ACCESS EXCLUSIVE). Данный режим гарантирует, что удерживающая его транзакция является единственной транзакцией, обращающейся к таблице любым способом.

Запрашивается командами DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL, и REFRESH MATERIALIZED VIEW (без CONCURRENTLY) команд. Многие формы ALTER INDEX и ALTER TABLE также запрашивают блокировку данного уровня. Данный режим блокировки также используется по умолчанию для LOCK TABLE в которых явно не указан режим.

Подсказка

Только ACCESS EXCLUSIVE блокировка блокирует SELECT (без FOR UPDATE/SHARE) оператор.

После получения блокировка обычно удерживается до завершения транзакции. Однако если блокировка получена после создания точки сохранения, она немедленно снимается при откате к этой точке. Это согласуется с принципом, согласно которому ROLLBACK отменяет все эффекты команд, выполненных после точки сохранения. То же самое относится к блокировкам, полученным внутри PL/pgSQL блока исключений: выход из блока при возникновении ошибки освобождает блокировки, полученные внутри него.

Таблица 2.10.2. Конфликтующие режимы блокировок

Запрошенный режим блокировкиСуществующий режим блокировки
ACCESS SHAREROW SHAREROW EXCL.SHARE UPDATE EXCL.SHARESHARE ROW EXCL.EXCL.ACCESS EXCL.
ACCESS SHARE       X
ROW SHARE      XX
ROW EXCL.    XXXX
SHARE UPDATE EXCL.   XXXXX
SHARE  XX XXX
SHARE ROW EXCL.  XXXXXX
EXCL. XXXXXXX
ACCESS EXCL.XXXXXXXX

2.10.3.2. Блокировки на уровне строк #

Помимо блокировок на уровне таблиц, существуют блокировки на уровне строк, которые перечислены ниже вместе с контекстами, в которых они автоматически используются в Digital Q.DataBase. См. Таблица 2.10.3 для получения полной таблицы конфликтов блокировок на уровне строк. Обратите внимание на то, что транзакция может удерживать конфликтующие блокировки одной и той же строки даже в разных подтранзакциях; однако во всех остальных случаях две транзакции не могут одновременно удерживать конфликтующие блокировки одной строки. Блокировки на уровне строк не влияют на выполнение запросов данных; они блокируют только процессы записи и блокировки к той же строке. Блокировки на уровне строк освобождаются при завершении транзакции или при откате к точке сохранения, аналогично блокировкам на уровне таблиц.

Режимы блокировок на уровне строк

FOR UPDATE

FOR UPDATE приводит к тому, что строки, выбранные SELECT оператором, блокируются так же, как при обновлении. Это предотвращает их блокировку, изменение или удаление другими транзакциями до завершения текущей транзакции. Таким образом, другие транзакции, пытающиеся выполнить UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR NO KEY UPDATE, SELECT FOR SHARE или SELECT FOR KEY SHARE для данных строк, будут приостановлены до завершения текущей транзакции; напротив, SELECT FOR UPDATE будет ожидать завершения параллельной транзакции, выполнившей любую из этих команд для той же самой строки, после чего заблокирует и вернет обновленную строку (или не вернет ничего, если строка была удалена). В рамках уровень изоляции Repeatable Read или уровень изоляции Serializable транзакция, однако в случае изменения подлежащей блокировке строки будет выдана ошибка с момента начала транзакции. Дополнительную информацию см. в Раздел 2.10.4.

Команда FOR UPDATE режим блокировки также запрашивается любой DELETE для строки, а также любой UPDATE изменяющей значения определенных столбцов. В настоящее время набор столбцов, рассматриваемых для данного UPDATE случая, включает те столбцы, для которых определен уникальный индекс, применимый во внешнем ключе (поэтому частичные индексы и индексы по выражениям не учитываются), но это может измениться в будущем.

FOR NO KEY UPDATE

Работает аналогично FOR UPDATE, за исключением того, что устанавливаемая блокировка является более слабой: данная блокировка не ограничивает SELECT FOR KEY SHARE команды, которые пытаются получить блокировку тех же самых строк. Данный режим блокировки также запрашивается любой UPDATE которая не запрашивает FOR UPDATE блокировку.

FOR SHARE

Работает аналогично FOR NO KEY UPDATE, за исключением того, что она запрашивает разделяемую блокировку вместо исключительной для каждой полученной строки. Разделяемая блокировка препятствует выполнению другими транзакциями UPDATE, DELETE, SELECT FOR UPDATE или SELECT FOR NO KEY UPDATE над этими строками, но она не препятствует выполнению ими SELECT FOR SHARE или SELECT FOR KEY SHARE.

FOR KEY SHARE

Работает аналогично FOR SHARE, за исключением того, что блокировка является более слабой: SELECT FOR UPDATE блокируется, но не SELECT FOR NO KEY UPDATE. Блокировка типа key-shared препятствует выполнению другими транзакциями DELETE или любых UPDATE которые изменяют значения ключей, но не другое UPDATE, и это также не предотвращает SELECT FOR NO KEY UPDATE, SELECT FOR SHARE, или SELECT FOR KEY SHARE.

Digital Q.DataBase не хранит информацию об измененных строках в оперативной памяти, поэтому количество одновременно заблокированных строк не ограничено. Однако блокировка строки может вызвать запись на диск, например, SELECT FOR UPDATE изменяет выбранные строки, помечая их как заблокированные, что приводит к операциям записи на диск.

Таблица 2.10.3. Конфликтующие блокировки на уровне строк

Запрошенный режим блокировкиТекущий режим блокировки
FOR KEY SHAREFOR SHAREFOR NO KEY UPDATEFOR UPDATE
FOR KEY SHARE   X
FOR SHARE  XX
FOR NO KEY UPDATE XXX
FOR UPDATEXXXX

2.10.3.3. Блокировки на уровне страниц #

В дополнение к блокировкам таблиц и строк, для управления доступом на чтение/запись к страницам таблиц в пуле общих буферов используются разделяемые и исключительные блокировки на уровне страниц. Эти блокировки снимаются сразу после извлечения или обновления строки. Разработчикам приложений обычно не требуется учитывать блокировки на уровне страниц, однако они упоминаются здесь для полноты изложения.

2.10.3.4. Взаимные блокировки #

Использование явного блокирования может повысить вероятность возникновения взаимные блокировки, при которой две (или более) транзакции удерживают блокировки, необходимые друг другу. Например, если транзакция 1 запрашивает исключительную блокировку таблицы A, а затем пытается получить исключительную блокировку таблицы B, в то время как транзакция 2 уже заблокировала таблицу B в исключительном режиме и теперь запрашивает исключительную блокировку таблицы A, ни одна из них не сможет продолжить выполнение. Digital Q.DataBase автоматически обнаруживает ситуации взаимной блокировки и разрешает их путем прерывания одной из задействованных транзакций, позволяя остальным завершиться. (Предсказать, какая именно транзакция будет прервана, сложно, поэтому не следует полагаться на конкретный выбор).

Следует отметить, что взаимные блокировки могут также возникать в результате блокировок на уровне строк (таким образом, они возможны даже без использования явного блокирования). Рассмотрим случай, в котором две параллельные транзакции изменяют таблицу. Первая транзакция выполняет команду:

UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 11111;

При этом запрашивается блокировка на уровне строк для строки с указанным номером счета. Затем выполняется вторая транзакция:

UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;

Первый UPDATE оператор успешно получает блокировку на уровне строк для указанной строки и обновляет ее. Однако второй UPDATE оператор обнаруживает, что строка, которую он пытается обновить, уже заблокирована, поэтому он ожидает завершения транзакции, удерживающей данную блокировку. Вторая транзакция ожидает завершения первой транзакции для продолжения своего выполнения. Теперь первая транзакция выполняет:

UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;

Первая транзакция пытается получить блокировку на уровне строк для указанной строки, но это невозможно, так как вторая транзакция уже удерживает такую блокировку. Вследствие этого она ожидает завершения второй транзакции. Таким образом, первая транзакция блокируется второй, а вторая транзакция — первой: возникает состояние взаимной блокировки. Digital Q.DataBase обнаружит данную ситуацию и прервет одну из транзакций.

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

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

2.10.3.5. Рекомендательные блокировки #

Digital Q.DataBase предоставляет средства для создания блокировок, значение которых определяется на уровне приложения. Такие блокировки называются рекомендательными блокировками, поскольку система не контролирует их использование — корректность их применения полностью возлагается на приложение. Рекомендательные блокировки могут быть полезны для стратегий блокирования, которые трудно реализовать в рамках модели MVCC. Например, рекомендательные блокировки часто используются для эмуляции стратегий пессимистической блокировки, характерных для так называемых «систем на основе плоских файлов» управления данными. Хотя для этой же цели можно было бы использовать флаг, хранящийся в таблице, метод рекомендательных блокировок работает быстрее, позволяет избежать раздувания таблиц и автоматически очищается сервером по завершении сеанса.

Существует два способа получить рекомендательную блокировку в Digital Q.DataBase: на уровне сеанса или на уровне транзакции. Рекомендательная блокировка, полученная на уровне сеанса, удерживается до тех пор, пока она не будет явно снята или пока не завершится сеанс. В отличие от стандартных запросов на блокировку, запросы на рекомендательную блокировку уровня сеанса не учитывают семантику транзакций: блокировка, полученная в транзакции, которая впоследствии была отменена, все равно будет удерживаться после отката; аналогично, снятие блокировки остается в силе, даже если вызвавшая его транзакция завершается ошибкой. Блокировка может быть получена владеющим процессом многократно; каждый выполненный запрос на блокировку должен сопровождаться соответствующим запросом на разблокировку, прежде чем блокировка будет фактически снята. Запросы на блокировку уровня транзакции, напротив, ведут себя аналогично обычным запросам: они автоматически снимаются по завершении транзакции, и для них не предусмотрена операция явного снятия блокировки. Данный механизм часто оказывается более удобным для краткосрочного использования рекомендательной блокировки, чем поведение на уровне сеанса. Запросы на получение блокировок на уровне сеанса и на уровне транзакции для одного и того же идентификатора рекомендательной блокировки будут блокировать друг друга ожидаемым образом. Если сеанс уже удерживает определенную рекомендательную блокировку, последующие запросы от него всегда будут успешными, даже если получения этой блокировки ожидают другие сеансы; Данное утверждение верно независимо от того, относятся ли существующая удерживаемая блокировка и новый запрос к уровню сессии или к уровню транзакции.

Как и в случае со всеми блокировками в Digital Q.DataBase, полный список рекомендательных блокировок, удерживаемых в настоящее время всеми сеансами, можно найти в pg_locks system view.

Как рекомендательные, так и обычные блокировки хранятся в пуле общей памяти, размер которого определяется конфигурационными переменными max_locks_per_transaction и max_connections. Необходимо следить за тем, чтобы не исчерпать данный объем памяти, иначе сервер не сможет выдать ни одной блокировки. Это устанавливает верхний предел количества рекомендательных блокировок, которые могут быть выданы сервером; как правило, это значение составляет от десятков до сотен тысяч в зависимости от конфигурации сервера.

В определенных случаях при использовании методов рекомендательных блокировок, особенно в запросах, включающих явную сортировку и LIMIT конструкциями, необходимо контролировать получение блокировок из-за порядка, в котором вычисляются SQL-выражения. Например:

SELECT pg_advisory_lock(id) FROM foo WHERE id = 12345; -- ok
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100; -- danger!
SELECT pg_advisory_lock(q.id) FROM
(
  SELECT id FROM foo WHERE id > 12345 LIMIT 100
) q; -- ok

В приведенных выше запросах вторая форма опасна, так как LIMIT не гарантируется применение ограничения до выполнения функции блокировки. Это может привести к установке блокировок, которые приложение не ожидало и, следовательно, не сможет освободить (до завершения сеанса). С точки зрения приложения такие блокировки будут «зависшими», хотя они по-прежнему отображаются в pg_locks.

Функции, предназначенные для управления рекомендательными блокировками, описаны в Раздел 2.6.28.10.

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению