Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  Functions and Operators  /  Locking Functions

14.14 锁定函数

本节描述了用于操作用户级锁的函数。

表 14.19 锁定函数

Name Description
GET_LOCK() 获取命名锁
IS_FREE_LOCK() 命名锁是否可用
IS_USED_LOCK() 命名锁是否正在使用;如果是,则返回连接标识符
RELEASE_ALL_LOCKS() 释放所有当前命名锁
RELEASE_LOCK() 释放命名锁

  • GET_LOCK(str,timeout)

    尝试获取一个名为 str 的锁,使用 timeout 秒的超时时间。如果 timeout 为负值,则表示无限超时时间。该锁是排他性的。在一个会话持有该锁时,其他会话无法获取同名锁。

    如果锁获取成功,则返回 1,如果超时(例如,另一个客户端已经锁定了该名称),则返回 0,如果发生错误(例如,内存不足或线程被杀死),则返回 NULL

    使用 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() 获取的唯一命名锁将出现在性能模式 metadata_locks 表中。OBJECT_TYPE 列显示 USER LEVEL LOCKOBJECT_NAME 列显示锁名称。在同一个名称下获取多个锁的情况下,只有第一个锁注册在 metadata_locks 表中。后续锁的获取不会注册新的元数据锁,而是增加锁的计数器。在释放最后一个锁实例时,metadata_locks 表中的行将被删除。

    由于可以获取多个锁,因此存在客户端之间死锁的可能性。当这种情况发生时,服务器将选择一个调用者,并以 ER_USER_LOCK_DEADLOCK 错误终止锁获取请求。该错误不会导致事务回滚。

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

    GET_LOCK() 可以用来实现应用程序锁或模拟记录锁。名称是在服务器范围内锁定的。如果一个名称已经在一个会话中锁定,GET_LOCK() 将阻止任何其他会话对同名锁的请求。这使得客户端可以使用锁名来执行合作式咨询锁。但是,需要注意的是,这也使得不在合作客户端集中的客户端可以锁定名称,从而阻止任何合作客户端锁定该名称。一个减少这种可能性的是使用数据库特定的或应用程序特定的锁名。例如,使用锁名的形式 db_name.strapp_name.str

    如果多个客户端等待锁,则它们获取锁的顺序是未定义的。应用程序不应该假设客户端以相同的顺序获取锁。

    GET_LOCK() 不适用于基于语句的复制。 如果使用该函数时 binlog_format 设置为 STATEMENT,将记录警告。

    由于 GET_LOCK() 只在单个 mysqld 上建立锁,因此它不适用于 NDB 集群,因为 NDB 集群无法跨多个 MySQL 服务器强制执行 SQL 锁。请参阅 第 25.2.7.10 节,“与多个 NDB 集群节点相关的限制”,以获取更多信息。

    Caution

    由于可以获取多个命名锁,因此单个语句可以获取大量锁。例如:

    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 时使用该函数,将记录警告。