Spec-Zone.ru › MySQL 9.2

14.14 Функции блокировки

В этом разделе описываются функции для управления блокировками на уровне пользователя.

Таблица 14.19 Функции блокировки

Таблица 14.19 Функции блокировки
Имя Описание
GET_LOCK() Получить именованную блокировку
IS_FREE_LOCK() Является ли именованная блокировка свободной
IS_USED_LOCK() Является ли именованная блокировка занятой; вернуть идентификатор соединения, если да
RELEASE_ALL_LOCKS() Освободить все текущие именованные блокировки
RELEASE_LOCK() Освободить именованную блокировку

  • GET_LOCK(str,timeout)

    Попытка получить блокировку с именем, заданным строкой str, используя таймаут timeout секунд. Отрицательное значение timeout означает бесконечный таймаут. Блокировка является исключительной. Пока она удерживается одной сессией, другие сессии не могут получить блокировку с таким же именем.

    Возвращает 1, если блокировка была успешно получена, 0, если попытка истекла (например, потому что другой клиент ранее заблокировал это имя), или NULL, если произошла ошибка (например, закончилась память или поток был убит с помощью mysqladmin kill).

    Блокировка, полученная с помощью GET_LOCK(), явно освобождается выполнением RELEASE_LOCK() или неявно при завершении сессии (как нормальном, так и аномальном). Блокировки, полученные с помощью GET_LOCK(), не освобождаются при подтверждении или откате транзакций.

    GET_LOCK() реализуется с помощью подсистемы блокировки метаданных (MDL). Можно получить несколько одновременных блокировок, и GET_LOCK() не освобождает какие-либо существующие блокировки. Например, предположим, что вы выполняете эти операторы:

    SELECT GET_LOCK('lock1',10);
    SELECT GET_LOCK('lock2',10);
    SELECT RELEASE_LOCK('lock2');
    SELECT RELEASE_LOCK('lock1');
    

    Вторая GET_LOCK() получает вторую блокировку, и оба вызова RELEASE_LOCK() возвращают 1 (успех).

    Даже одна сессия может получить несколько блокировок для одного и того же имени. Другие сессии не могут получить блокировку с этим именем, пока приобретающая сессия не освободит все свои блокировки для этого имени.

    Блокировки с уникальными именами, полученные с помощью GET_LOCK(), отображаются в таблице Performance Schema metadata_locks. Столбец OBJECT_TYPE содержит значение USER LEVEL LOCK, а столбец OBJECT_NAME указывает имя блокировки. В случае получения нескольких блокировок для одного и того же имени, только первая блокировка для этого имени записывает строку в таблицу metadata_locks. Последующие блокировки для этого имени увеличивают счетчик в блокировке, но не приобретают дополнительных блокировок метаданных. Строка metadata_locks для блокировки удаляется, когда последний экземпляр блокировки для этого имени освобождается.

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

    MySQL накладывает максимальную длину имени блокировки в 64 символа.

    GET_LOCK() может использоваться для реализации прикладных блокировок или имитации блокировок записей. Имена блокируются на уровне всего сервера. Если имя заблокировано в одной сессии, GET_LOCK() блокирует любой запрос другой сессии на получение блокировки с тем же именем. Это позволяет клиентам, договорившимся об имени блокировки, использовать его для выполнения кооперативного консультативного блокирования. Но следует иметь в виду, что это также позволяет клиенту, который не входит в набор взаимодействующих клиентов, заблокировать имя, случайно или намеренно, и тем самым предотвратить блокирование этого имени любыми взаимодействующими клиентами. Один из способов уменьшить вероятность этого — использовать имена блокировок, специфичные для базы данных или приложения. Например, используйте имена блокировок в формате db_name.str или app_name.str.

    Если несколько клиентов ожидают блокировку, порядок, в котором они ее получают, не определен. Приложения не должны предполагать, что клиенты получают блокировку в том же порядке, в котором они подавали запросы на блокировку.

    GET_LOCK() небезопасен для репликации на основе операторов. Если вы используете эту функцию, когда binlog_format установлено в STATEMENT, регистрируется предупреждение.

    Поскольку GET_LOCK() устанавливает блокировку только на одном mysqld, она не подходит для использования с NDB Cluster, у которого нет способа принудительного применения SQL-блокировки через несколько серверов MySQL. Дополнительную информацию см. в Разделе 25.2.7.10 «Ограничения, связанные с несколькими узлами NDB Cluster».

    Внимание

    Благодаря возможности получения нескольких именованных блокировок, один оператор может получить большое количество блокировок. Например:

    INSERT INTO ... SELECT GET_LOCK(t1.col_name) FROM t1;
    

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

    Доступен другой интерфейс блокировки в виде плагина или набора загружаемых функций. Этот интерфейс предоставляет имена пространств блокировок и отдельные блокировки чтения и записи, в отличие от интерфейса, предоставляемого функциями GET_LOCK() и связанными функциями. Подробности см. в Разделе 7.6.9.1 «Сервис блокировок».

  • IS_FREE_LOCK(str)

    Проверяет, доступна ли блокировка с именем str (т. е. не заблокирована). Возвращает 1, если блокировка свободна (никто не использует блокировку), 0, если блокировка используется, и NULL, если произошла ошибка (например, неверный аргумент).

    Эта функция небезопасна для репликации на основе операторов. При использовании этой функции, когда binlog_format установлено в STATEMENT, регистрируется предупреждение.

  • IS_USED_LOCK(str)

    Проверяет, используется ли блокировка с именем str (т. е. заблокирована). Если это так, возвращает идентификатор соединения сессии клиента, которая удерживает блокировку. В противном случае возвращает NULL.

    Эта функция небезопасна для репликации на основе операторов. При использовании этой функции, когда binlog_format установлено в STATEMENT, регистрируется предупреждение.

  • RELEASE_ALL_LOCKS()

    Освобождает все именованные блокировки, удерживаемые текущей сессией, и возвращает количество освобожденных блокировок (0, если их не было).

    Эта функция небезопасна для репликации на основе операторов. При использовании этой функции, когда binlog_format установлено в STATEMENT, регистрируется предупреждение.

  • RELEASE_LOCK(str)

    Освобождает блокировку с именем, заданным строкой str, которая была получена с помощью GET_LOCK(). Возвращает 1, если блокировка была освобождена, 0, если блокировка не была установлена этим потоком (в этом случае блокировка не освобождается), и NULL, если именованной блокировки не существовало. Блокировка не существует, если она никогда не была получена вызовом GET_LOCK() или если она была ранее освобождена.

    Оператор DO удобно использовать с RELEASE_LOCK(). См. Раздел 15.2.3 «Оператор DO».

    Эта функция небезопасна для репликации на основе операторов. При использовании этой функции, когда binlog_format установлено в STATEMENT, регистрируется предупреждение.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/locking-functions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API