Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 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()获取唯一命名锁定的锁定将出现在性能chema的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集群没有办法强制SQL锁定跨越多个MySQL服务器。请参阅第25.2.7.10节,“ Limitations Relating to Multiple NDB Cluster Nodes”,了解更多信息。

    Caution

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

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

    这些类型的语句可能会产生某些不良影响。例如,如果语句在执行过程中失败并回滚,到达失败点之前获取的锁定仍然存在。如果意图是将插入的行与获取的锁定对应,那么这个意图不能满足。此外,如果需要确保锁定的顺序,请注意结果集顺序可能会因优化器选择的执行计划而不同。因此,可能最好限制应用程序到单个锁定获取调用语句。

    另一个锁定接口可作为插件服务或可加载函数提供。这个接口提供锁定命名空间和读写锁定,而不是GET_LOCK()和相关函数提供的接口。请参阅第7.6.9.1节,“The Locking Service”,了解更多信息。

  • 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,将记录警告。