Spec-Zone.ru › MySQL 5.7

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

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

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

Таблица 12.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(), не освобождаются при подтверждении или откате транзакций.

    В MySQL 5.7, GET_LOCK() была переделана с использованием подсистемы блокировок метаданных (MDL) и её возможности были расширены. Можно получить несколько одновременных блокировок, и GET_LOCK() не освобождает существующие блокировки.

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

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

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

    До MySQL 5.7 можно получить только одну одновременную блокировку, и GET_LOCK() освобождает любую существующую блокировку. Разница в поведении получения блокировки, начиная с MySQL 5.7, показана на следующем примере. Предположим, что вы выполняете эти инструкции:

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

    В MySQL 5.7 или более поздних версиях второй GET_LOCK() получает вторую блокировку, и оба вызова RELEASE_LOCK() возвращают 1 (успех). До MySQL 5.7 второй GET_LOCK() освобождает первую блокировку ('lock1') и второй RELEASE_LOCK() возвращает NULL (ошибка), потому что нет 'lock1' для освобождения.

    MySQL 5.7 и более поздние версии накладывают максимальную длину на имена блокировок в 64 символа. Раньше никакого ограничения не было.

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

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

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

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

    Предупреждение

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

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

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

    Доступен другой интерфейс блокировки в виде плагина или набора загружаемых функций. Этот интерфейс предоставляет пространства имён блокировок и отдельные блокировки чтения и записи, в отличие от интерфейса, предоставляемого GET_LOCK() и связанными функциями. Подробнее см. Раздел 5.5.6.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(). См. Раздел 13.2.3, «Инструкция DO».

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

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

Spec-Zone.ru

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