本节描述了用于操作用户级锁的函数。
表 14.19 锁定函数
Name | Description |
---|---|
GET_LOCK() |
获取命名锁 |
IS_FREE_LOCK() |
命名锁是否可用 |
IS_USED_LOCK() |
命名锁是否正在使用;如果是,则返回连接标识符 |
RELEASE_ALL_LOCKS() |
释放所有当前命名锁 |
RELEASE_LOCK() |
释放命名锁 |
-
尝试获取一个名为
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 LOCK
,OBJECT_NAME
列显示锁名称。在同一个名称下获取多个锁的情况下,只有第一个锁注册在metadata_locks
表中。后续锁的获取不会注册新的元数据锁,而是增加锁的计数器。在释放最后一个锁实例时,metadata_locks
表中的行将被删除。由于可以获取多个锁,因此存在客户端之间死锁的可能性。当这种情况发生时,服务器将选择一个调用者,并以
ER_USER_LOCK_DEADLOCK
错误终止锁获取请求。该错误不会导致事务回滚。MySQL 对锁名称的最大长度限制为 64 个字符。
GET_LOCK()
可以用来实现应用程序锁或模拟记录锁。名称是在服务器范围内锁定的。如果一个名称已经在一个会话中锁定,GET_LOCK()
将阻止任何其他会话对同名锁的请求。这使得客户端可以使用锁名来执行合作式咨询锁。但是,需要注意的是,这也使得不在合作客户端集中的客户端可以锁定名称,从而阻止任何合作客户端锁定该名称。一个减少这种可能性的是使用数据库特定的或应用程序特定的锁名。例如,使用锁名的形式db_name.str
或app_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 节,“锁服务”。 -
检查名为
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()
结合使用非常方便。请参阅 第 15.2.3 节,“DO 语句”。该函数不适用于基于语句的复制。 如果您在
binlog_format
设置为STATEMENT
时使用该函数,将记录警告。