12.14 Функции блокировки
В этом разделе описываются функции, используемые для управления блокировками на уровне пользователя.
Таблица 12.19 Функции блокировки
| Имя | Описание |
|---|---|
GET_LOCK() | Получить именованную блокировку |
IS_FREE_LOCK() | Является ли именованная блокировка свободной |
IS_USED_LOCK() | Используется ли именованная блокировка; вернуть идентификатор подключения, если да |
RELEASE_ALL_LOCKS() | Освободить все текущие именованные блокировки |
RELEASE_LOCK() | Освободить именованную блокировку |
-
Попытка получить блокировку с именем, заданным строкой
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 Schemametadata_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, «Служба блокировки». -
Проверяет, свободна ли для использования блокировка с именем
str(то есть не заблокирована). Возвращает1, если блокировка свободна (никто не использует блокировку),0, если блокировка используется, иNULL, если произошла ошибка (например, неверный аргумент).Эта функция небезопасна для репликации на основе инструкций. Выводится предупреждение, если вы используете эту функцию, когда
binlog_formatустановлено вSTATEMENT. -
Проверяет, используется ли блокировка с именем
str(то есть заблокирована). Если да, возвращает идентификатор соединения клиента, который удерживает блокировку. В противном случае возвращаетNULL.Эта функция небезопасна для репликации на основе инструкций. Выводится предупреждение, если вы используете эту функцию, когда
binlog_formatустановлено вSTATEMENT. -
Освобождает все именованные блокировки, удерживаемые текущей сессией, и возвращает количество освобождённых блокировок (0, если их не было).
Эта функция небезопасна для репликации на основе инструкций. Выводится предупреждение, если вы используете эту функцию, когда
binlog_formatустановлено вSTATEMENT. -
Освобождает блокировку с именем, заданным строкой
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.