## 12.15 锁定功能

[](<>)[](<>)

本节介绍用于操作用户级锁的函数。

[](<>)

**表 12.19 锁定功能**

| 姓名 | 描述 |
| --- | --- |
| [`GET_LOCK()`](locking-functions.html#function_get-lock) | 获取命名锁 |
| [`IS_FREE_LOCK()`](locking-functions.html#function_is-free-lock) | 命名锁是否空闲 |
| [`IS_USED_LOCK()`](locking-functions.html#function_is-used-lock) | 命名锁是否在使用中；如果为真，则返回连接标识符 |
| [`RELEASE_ALL_LOCKS()`](locking-functions.html#function_release-all-locks) | 释放所有当前的命名锁 |
| [`RELEASE_LOCK()`](locking-functions.html#function_release-lock) | 释放命名锁 |

-   [](<>)

    [`GET_LOCK(*`字符串`*,*`暂停`*)`](locking-functions.html#function_get-lock)

    [](<>)[](<>)

    尝试使用字符串给出的名称获取锁*`字符串`*，使用超时*`暂停`*秒。一个负面的*`暂停`*value 表示无限超时。锁是独占的。当一个会话持有时，其他会话不能获得同名的锁。

    退货`1`如果成功获得锁，`0`如果尝试超时（例如，因为另一个客户端先前已锁定该名称），或者`空值`如果发生错误（例如内存不足或线程被杀死）[**mysqladmin 杀**](mysqladmin.html)）。

    获得的锁[`GET_LOCK()`](locking-functions.html#function_get-lock)通过执行显式释放[`RELEASE_LOCK()`](locking-functions.html#function_release-lock)或在您的会话终止时（正常或异常）隐式终止。获得的锁[`GET_LOCK()`](locking-functions.html#function_get-lock)事务提交或回滚时不会释放。

    [`GET_LOCK()`](locking-functions.html#function_get-lock)使用元数据锁定 (MDL) 子系统实现。可以同时获取多个锁，并且[`GET_LOCK()`](locking-functions.html#function_get-lock)不释放任何现有的锁。例如，假设您执行以下语句：

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

    第二[`GET_LOCK()`](locking-functions.html#function_get-lock)获得第二个锁和两者[`RELEASE_LOCK()`](locking-functions.html#function_release-lock)调用返回 1（成功）。

    一个给定的会话甚至可以为同一个名字获取多个锁。在获取会话释放其对该名称的所有锁之前，其他会话无法获取具有该名称的锁。

    获得的唯一命名锁[`GET_LOCK()`](locking-functions.html#function_get-lock)出现在性能架构中[`元数据锁`](performance-schema-metadata-locks-table.html)桌子。这`OBJECT_TYPE`专栏说`用户等级锁定`和`OBJECT_NAME`列表示锁名称。在获取多个锁的情况下*相同的*name，只有 name 的第一个锁在[`元数据锁`](performance-schema-metadata-locks-table.html)桌子。名称的后续锁会增加锁中的计数器，但不会获取额外的元数据锁。这[`元数据锁`](performance-schema-metadata-locks-table.html)当名称上的最后一个锁实例被释放时，锁的行被删除。

    获取多个锁的能力意味着客户端之间存在死锁的可能性。当这种情况发生时，服务器会选择一个调用者并终止它的锁获取请求。[`ER_USER_LOCK_DEADLOCK`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_user_lock_deadlock)错误。此错误不会导致事务回滚。

    MySQL 强制锁定名称的最大长度为 64 个字符。

    [`GET_LOCK()`](locking-functions.html#function_get-lock)可用于实现应用程序锁或模拟记录锁。名称在服务器范围内被锁定。如果一个名字在一个会话中被锁定，[`GET_LOCK()`](locking-functions.html#function_get-lock)阻止另一个会话对同名锁的任何请求。这使同意给定锁名称的客户端能够使用该名称来执行协作咨询锁定。但请注意，它还会使不在合作客户端集合中的客户端无意或故意锁定名称，从而防止任何合作客户端锁定该名称。降低这种可能性的一种方法是使用特定于数据库或特定于应用程序的锁名称。例如，使用形式的锁名称*`db_name.str`*要么*`app_name.str`*.

    如果多个客户端正在等待一个锁，它们获取锁的顺序是不确定的。应用程序不应假定客户端获取锁的顺序与它们发出锁请求的顺序相同。

    [`GET_LOCK()`](locking-functions.html#function_get-lock)对于基于语句的复制是不安全的。如果您在以下情况下使用此功能，则会记录警告[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`.

    自从`GET_LOCK()`仅在单个上建立锁定[**mysqld**](mysqld.html)，它不适合与 NDB Cluster 一起使用，它无法跨多个 MySQL 服务器强制执行 SQL 锁。看[第 23.2.7.10 节，“与多个 NDB 集群节点相关的限制”](mysql-cluster-limitations-multiple-nodes.html)， 了解更多信息。

    警告

    有了获取多个命名锁的能力，一条语句就可以获取大量的锁。例如：

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

    这些类型的陈述可能会产生某些不利影响。例如，如果语句中途失败并回滚，则在失败点之前获取的锁仍然存在。如果意图是在插入的行和获取的锁之间存在对应关系，则不满足该意图。此外，如果按特定顺序授予锁很重要，请注意结果集顺序可能因优化器选择的执行计划而异。由于这些原因，最好将应用程序限制为每个语句的单个锁获取调用。

    不同的锁定接口可用作插件服务或一组可加载功能。这个接口提供了锁命名空间和不同的读写锁，不像提供的接口[`GET_LOCK()`](locking-functions.html#function_get-lock)及相关功能。有关详细信息，请参阅[第 5.6.9.1 节，“锁定服务”](locking-service.html).

-   [](<>)

    [`IS_FREE_LOCK(*`字符串`*)`](locking-functions.html#function_is-free-lock)

    [](<>)

    检查锁是否命名*`字符串`*可以免费使用（即未锁定）。退货`1`如果锁是空闲的（没有人使用锁），`0`如果锁正在使用中，并且`空值`如果发生错误（例如不正确的参数）。

    此函数对于基于语句的复制是不安全的。如果您在以下情况下使用此功能，则会记录警告[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`.

-   [](<>)

    [`IS_USED_LOCK(*`字符串`*)`](locking-functions.html#function_is-used-lock)

    [](<>)

    检查锁是否命名*`字符串`*正在使用中（即锁定）。如果是，则返回持有锁的客户端会话的连接标识符。否则，它返回`空值`.

    此函数对于基于语句的复制是不安全的。如果您在以下情况下使用此功能，则会记录警告[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`.

-   [](<>)

    [`RELEASE_ALL_LOCKS()`](locking-functions.html#function_release-all-locks)

    [](<>)

    释放当前会话持有的所有命名锁，并返回释放的锁数（如果没有，则为 0）

    此函数对于基于语句的复制是不安全的。如果您在以下情况下使用此功能，则会记录警告[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`.

-   [](<>)

    [`释放_锁（*`字符串`*)`](locking-functions.html#function_release-lock)

    [](<>)

    释放由字符串命名的锁*`字符串`*那是用[`GET_LOCK()`](locking-functions.html#function_get-lock).退货`1`如果锁被释放，`0`如果该线程没有建立锁（在这种情况下，锁没有被释放），并且`空值`如果命名锁不存在。如果从未通过调用获得该锁，则该锁不存在[`GET_LOCK()`](locking-functions.html#function_get-lock)或者如果它之前已发布。

    这[`做`](do.html)语句使用起来很方便[`RELEASE_LOCK()`](locking-functions.html#function_release-lock).看[第 13.2.3 节，“DO 声明”](do.html).

    此函数对于基于语句的复制是不安全的。如果您在以下情况下使用此功能，则会记录警告[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)被设定为`陈述`.
