Spec-Zone.ru › MariaDB

GET_LOCK

Синтаксис

GET_LOCK(str,timeout)

Описание

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

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

Функция IS_FREE_LOCK возвращает, свободна ли указанная блокировка, а IS_USED_LOCK — используется ли она.

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

Также возможно рекурсивное установление той же блокировки. Если блокировка с тем же именем устанавливается n раз, ее необходимо освободить n раз.

str нечувствительно к регистру для GET_LOCK() и связанных функций. Если str пустая строка или NULL, то GET_LOCK() возвращает NULL и ничего не делает. timeout поддерживает микросекунды.

Если плагин metadata_lock_info установлен, блокировки, полученные с помощью этой функции, видны в таблице Information Schema METADATA_LOCK_INFO.

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

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

Патч, позволяющий использовать несколько блокировок, был представлен Константином "Kostja" Osipov (MDEV-3917).

Примеры

SELECT GET_LOCK('lock1',10);
+----------------------+
| GET_LOCK('lock1',10) |
+----------------------+
|                    1 |
+----------------------+

SELECT IS_FREE_LOCK('lock1'), IS_USED_LOCK('lock1');
+-----------------------+-----------------------+
| IS_FREE_LOCK('lock1') | IS_USED_LOCK('lock1') |
+-----------------------+-----------------------+
|                     0 |                    46 |
+-----------------------+-----------------------+

SELECT IS_FREE_LOCK('lock2'), IS_USED_LOCK('lock2');
+-----------------------+-----------------------+
| IS_FREE_LOCK('lock2') | IS_USED_LOCK('lock2') |
+-----------------------+-----------------------+
|                     1 |                  NULL |
+-----------------------+-----------------------+

Можно удерживать несколько блокировок:

SELECT GET_LOCK('lock2',10);
+----------------------+
| GET_LOCK('lock2',10) |
+----------------------+
|                    1 |
+----------------------+

SELECT IS_FREE_LOCK('lock1'), IS_FREE_LOCK('lock2');
+-----------------------+-----------------------+
| IS_FREE_LOCK('lock1') | IS_FREE_LOCK('lock2') |
+-----------------------+-----------------------+
|                     0 |                     0 |
+-----------------------+-----------------------+

SELECT RELEASE_LOCK('lock1'), RELEASE_LOCK('lock2');
+-----------------------+-----------------------+
| RELEASE_LOCK('lock1') | RELEASE_LOCK('lock2') |
+-----------------------+-----------------------+
|                     1 |                     1 |
+-----------------------+-----------------------+

Можно удерживать одну и ту же блокировку рекурсивно. Этот пример отображается с помощью плагина metadata_lock_info:

SELECT GET_LOCK('lock3',10);
+----------------------+
| GET_LOCK('lock3',10) |
+----------------------+
|                    1 |
+----------------------+

SELECT GET_LOCK('lock3',10);
+----------------------+
| GET_LOCK('lock3',10) |
+----------------------+
|                    1 |
+----------------------+

SELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;
+-----------+---------------------+---------------+-----------+--------------+------------+
| THREAD_ID | LOCK_MODE           | LOCK_DURATION | LOCK_TYPE | TABLE_SCHEMA | TABLE_NAME |
+-----------+---------------------+---------------+-----------+--------------+------------+
|        46 | MDL_SHARED_NO_WRITE | NULL          | User lock | lock3        |            |
+-----------+---------------------+---------------+-----------+--------------+------------+

SELECT RELEASE_LOCK('lock3');
+-----------------------+
| RELEASE_LOCK('lock3') |
+-----------------------+
|                     1 |
+-----------------------+

SELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;
+-----------+---------------------+---------------+-----------+--------------+------------+
| THREAD_ID | LOCK_MODE           | LOCK_DURATION | LOCK_TYPE | TABLE_SCHEMA | TABLE_NAME |
+-----------+---------------------+---------------+-----------+--------------+------------+
|        46 | MDL_SHARED_NO_WRITE | NULL          | User lock | lock3        |            |
+-----------+---------------------+---------------+-----------+--------------+------------+

SELECT RELEASE_LOCK('lock3');
+-----------------------+
| RELEASE_LOCK('lock3') |
+-----------------------+
|                     1 |
+-----------------------+

SELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;
Empty set (0.000 sec)

Пример с таймаутом: Соединение 1:

SELECT GET_LOCK('lock4',10);
+----------------------+
| GET_LOCK('lock4',10) |
+----------------------+
|                    1 |
+----------------------+

Соединение 2:

SELECT GET_LOCK('lock4',10);

Через 10 секунд...

+----------------------+
| GET_LOCK('lock4',10) |
+----------------------+
|                    0 |
+----------------------+

Дедлоки автоматически обнаруживаются и разрешаются. Соединение 1:

SELECT GET_LOCK('lock5',10); 
+----------------------+
| GET_LOCK('lock5',10) |
+----------------------+
|                    1 |
+----------------------+

Соединение 2:

SELECT GET_LOCK('lock6',10);
+----------------------+
| GET_LOCK('lock6',10) |
+----------------------+
|                    1 |
+----------------------+

Соединение 1:

SELECT GET_LOCK('lock6',10); 
+----------------------+
| GET_LOCK('lock6',10) |
+----------------------+
|                    0 |
+----------------------+

Соединение 2:

SELECT GET_LOCK('lock5',10);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

См. также

  • RELEASE_LOCK
  • IS_FREE_LOCK
  • IS_USED_LOCK
  • RELEASE_ALL_LOCKS
Содержание, воспроизведенное на этом сайте, является собственностью его соответствующих владельцев, и это содержание не проверяется предварительно MariaDB. Мнения, информация и мнения, выраженные в этом содержании, не обязательно отражают точку зрения MariaDB или любой другой стороны.

© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/get_lock/

Spec-Zone.ru

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