MySQL发行版提供了一个锁定接口,可在两个级别访问:
在SQL级别,作为一组可加载的函数,每个可加载函数将每个映射到服务例程调用。
作为一个C语言接口,可作为一个插件服务从服务器插件或可加载函数调用。
有关插件服务的一般信息,请参阅第5.6.9节,“MySQL插件服务”。有关可加载功能的一般信息,请参阅添加可加载功能。
锁定界面具有这些特性:
锁有三个属性:锁命名空间、锁名称和锁模式:
锁定通过命名空间和锁名的组合来识别。命名空间使不同的应用程序能够通过在单独的命名空间中创建锁而不碰撞而无需碰撞。例如,如果应用程序A和B使用名称空间
ns1
和ns2
,每个应用程序都可以使用锁名lock1
和lock2
不干扰其他应用程序。锁模式可以是读模式,也可以是写模式。读锁是共享的:如果一个会话在一个给定的锁标识符上有一个读锁,那么其他会话可以在同一个标识符上获得一个读锁。写锁是排他的:如果一个会话在一个给定的锁标识上有一个写锁,其他会话就不能获得同一个标识上的读或写锁。
命名空间和锁名称必须是非
空值
,非空,最大长度为64个字符。指定为的命名空间或锁名称空值
,或长度超过64个字符的字符串将导致ER_LOCKING_SERVICE_WRONG_NAME
错误。锁定接口将命名空间和锁名称视为二进制字符串,因此比较区分大小写。
锁定接口提供了获取锁和释放锁的函数。调用这些函数不需要特殊权限。权限检查是调用应用程序的责任。
如果没有立即可用,可以等待锁定。锁定采集呼叫采取整数超时值,指示在放弃之前等待锁的等待秒数。如果没有成功锁定采集,则达到超时,则
er_locking_service_timeout.
发生错误。如果超时为0,则没有等待,如果无法立即获取锁定,则呼叫会产生错误。锁定接口在不同的会话中检测锁采集呼叫之间的死锁。在这种情况下,锁定服务选择呼叫者并终止其锁定获取请求
er_locking_service_deadlock.
错误。此错误不会导致交易回滚。要选择会话,请在死锁时,锁定服务更喜欢在保持写入锁的会话上保存读取锁的会话。一个会话可以通过一个锁获取调用获得多个锁。对于给定的调用,锁获取是原子性的:如果所有的锁都被获取,调用就会成功。如果获取任何锁失败,则调用不获取任何锁并失败,通常使用
er_locking_service_timeout.
或者er_locking_service_deadlock.
错误。会话可以为相同的锁定标识符获取多个锁(命名空间和锁名组合)。这些锁定实例可以读取锁,写入锁或两者的混合。
通过调用release-locks函数显式释放会话中获得的锁,或者在会话终止(正常或异常)时隐式释放。事务提交或回滚时不会释放锁。
在会话中,给定名称空间的所有锁在释放时一起释放。
锁定服务提供的界面不同于提供的界面get_lock()
和相关的SQL函数(见第12.15节,“锁定函数”)。例如,get_lock()
不实现命名空间并仅提供独占锁,而不是不同的读取和写入锁。
介绍如何使用锁定服务的C语言接口。要使用函数接口,请参见5.6.9.1.2“锁定服务功能界面”对于锁定服务界面的一般特征,请参阅第5.6.9.1节“锁定服务”。有关插件服务的一般信息,请参阅第5.6.9节,“MySQL插件服务”。
使用锁定服务的源文件应包括此头文件:
#include
要获取一个或多个锁,调用这个函数:
int mysql_acquire_locking_service_locks(MYSQL_THD opaque_thd, const char**lock_names, size_t lock_num, enum enum_locking_service_lock_type lock_type, unsigned long lock_timeout);
这些参数有以下含义:
opaque_thd
:线程句柄。如果指定为空值
,使用当前线程的手柄。lock_namespace.
:一个以空结束的字符串,表示锁命名空间。lock_names
:一系列空终止字符串,提供锁的名称来获取。lock_num
:姓名的数量lock_names
大批。lock_type.
:锁定模式LOCKING_SERVICE_READ
或者LOCKING_SERVICE_WRITE
分别获取读锁或写入锁。lock_timeout
:在放弃之前等待获取锁的整数秒数。
要释放为给定命名空间获取的锁,调用这个函数:
int mysql_release_locking_service_locks(mysql_thd opaque_thd,const char * lock_namesace);
这些参数有以下含义:
opaque_thd
:线程句柄。如果指定为空值
,使用当前线程的手柄。lock_namespace.
:一个以空结束的字符串,表示锁命名空间。
可以使用Performance Schema在SQL级别监视锁定服务获取或等待的锁。有关详细信息,请参见锁定服务监控。
本节介绍如何使用其可加载函数提供的锁定服务接口。要使用C语言接口,请参见第5.6.9.1.1节,“锁定服务C接口”对于锁定服务界面的一般特征,请参阅第5.6.9.1节“锁定服务”。有关可加载功能的一般信息,请参阅添加可加载功能。
描述的锁定服务例程第5.6.9.1.1节,“锁定服务C接口”不需要安装,因为它们内置在服务器中。对于映射到服务例程调用的可加载函数则不是这样:函数在使用前必须安装。本节将介绍如何做到这一点。有关可加载功能安装的一般信息,请参见第5.7.1节,“安装和卸载可加载功能”。
锁定服务功能在位于名为的目录中的插件库文件中实现plugin_dir.
系统变量。文件基数是locking_service
。文件名后缀每个平台不同(例如,所以
对于UNIX和UNIX的系统,.dll.
对于Windows)。
要安装锁定服务功能,请使用创建功能
声明中,调整所以
必要时为您的平台后缀:
CREATE FUNCTION service_get_read_locks RETURNS INT SONAME 'locking_service.so';创建函数service_get_write_locks返回INT SONAME 'locking_service.so';创建函数service_release_locks返回INT SONAME 'locking_service.so';
如果在复制源服务器上使用这些功能,请将其安装在所有复制服务器上,以避免复制问题。
一旦安装完毕,函数将一直保持安装状态,直到卸载。要去除它们,请使用删除功能
声明:
删除函数service_get_read_locks;删除函数service_get_write_locks;删除功能service_release_locks;
在使用锁定服务功能之前,根据提供的说明安装它们安装/卸载锁定服务功能界面。
要获取一个或多个读锁,请调用此函数:
mysql>选择service_get_read_locks('mynameSpace','rlock1','rlock2',10);+ -------------------------------------------------------- + |service_get_read_locks('mynameSpace','rlock1','rlock2',10)|+ -------------------------------------------------------- + |1 |+ --------------------------------------------------------- +
第一个参数是锁名称空间。最后一个参数是一个整数超时,它指示在放弃之前需要等待多少秒才能获得锁。其中的参数是锁名。
对于刚才显示的示例,该函数获取带有锁标识符的锁(MyNamespace,Rlock1)
和(MyNamespace,Rlock2)
。
要获取写锁而不是读锁,调用这个函数:
mysql> SELECT service_get_write_locks('mynamespace', 'wlock1', 'wlock2', 10);+----------------------------------------------------------------+ | service_get_write_locks(‘mynamespace’,‘wlock1’,‘wlock2’,10 ) | +----------------------------------------------------------------+ | 1 | +----------------------------------------------------------------+
在本例中,锁标识符为(mynamespace wlock1)
和(mynamespace wlock2)
。
要释放名称空间的所有锁,请使用此功能:
mysql>选择service_release_locks('mynameSpace');+ -------------------------------------------------service_release_locks('mynameSpace')|+ -------------------------------------------------1 |+ -----------------------------------
每个锁定功能都返回非零成功。如果函数失败,则会发生错误。例如,发生以下错误,因为锁名名称不能为空:
mysql> SELECT service_get_read_locks('mynamespace', ", 10);ERROR 3131(42000):错误的锁定服务锁名称。
会话可以为相同的锁定标识获取多个锁。只要不同的会话没有用于标识符的写入锁,会话可以获取任何数量的读取或写入锁。每个锁定请求的标识符获取新锁。以下语句获取具有相同标识符的三个写入锁,然后为相同标识符进行三个读取锁:
选择service_get_write_locks('ns','lock1','lock1','lock1',0);选择service_get_read_locks('ns','lock1','lock1','lock1',0);
如果您检查表现模式metadata_locks
表中,您会发现会话持有6个不同的锁(ns, lock1)
标识符。(有关详细信息,请参阅锁定服务监控。)
因为会话至少包含一个写入锁(ns, lock1)
,其他会话可以为其获取锁,读取或写入。如果会话仅持有读取标识符的锁锁,则其他会话可以为其获取读取锁,但不是写入锁定。
单个锁获取调用的锁是以原子方式获取的,但是在调用之间不存在原子性。因此,对于下面这样的语句,其中service_get_write_locks ()
在结果集中每一行调用一次,原子性为每个单独的调用保留,但不为整个语句保留:
从T1中选择service_get_write_locks('ns','lock1','lock2',0)其中......;
由于锁定服务返回一个单独的锁,了解给定锁定标识符的每个成功请求,因为单个语句可以获取大量锁。例如:
插入……选择service_get_write_locks (ns, t1。col_name, 0) FROM t1;
这些类型的陈述可能有一定的负面影响。例如,如果语句部分失败并回滚,那么在故障点之前获得的锁仍然存在。如果意图是插入的行和获得的锁之间有对应关系,那么这个意图就不满足。另外,如果以某种顺序授予锁很重要,请注意,根据优化器选择的执行计划,结果集顺序可能会有所不同。由于这些原因,最好将应用程序限制为每个语句只能有一个锁获取调用。
锁服务是使用MySQL Server元数据锁框架实现的,因此您可以通过检查Performance Schema来监视获得或等待的锁服务锁metadata_locks
桌子。
首先,启用元数据锁工具:
MySQL>更新performence_schema.setup_instruments集启用='yes' - >其中name ='wait / lock / metadata / sql / mdl';
然后获取一些锁并检查metadata_locks
桌子:
mysql> SELECT service_get_write_locks('mynamespace', 'lock1', 0);+----------------------------------------------------+ | service_get_write_locks (' mynamespace ', ' lock1 ', 0 ) | +----------------------------------------------------+ | 1 | +----------------------------------------------------+ mysql >选择service_get_read_locks(“mynamespace”、“lock2”,0);+---------------------------------------------------+ | service_get_read_locks (' mynamespace ', ' lock2 ', 0 ) | +---------------------------------------------------+ | 1 | +---------------------------------------------------+ mysql >选择OBJECT_TYPE OBJECT_SCHEMA、OBJECT_NAME LOCK_TYPE LOCK_STATUS——从performance_schema >。metadata_locks——> OBJECT_TYPE = '锁定服务' \ G *************************** 1。行 *************************** OBJECT_TYPE:锁定服务OBJECT_SCHEMA: mynamespace OBJECT_NAME: lock1 LOCK_TYPE:独家LOCK_STATUS:理所当然 *************************** 2。行*************************** OBJECT_TYPE: LOCKING SERVICE OBJECT_SCHEMA: mynamespace OBJECT_NAME: lock2 LOCK_TYPE: SHARED LOCK_STATUS: GRANTED
锁定服务锁有一个object_type.
的价值锁定服务
。这与例如使用的锁定不同get_lock()
功能,有一个object_type.
的用户级锁
。
锁定命名空间,名称和模式出现在object_schema.
那OBJECT_NAME
, 和lock_type.
列。读和写锁有lock_type.
的值共享
和独家的
, 分别。
这LOCK_STATUS
价值是的确
对于已获得的锁,等待
对于被等待的锁。你可以期待看到等待
如果一个会话持有一个写锁,而另一个会话试图获取一个具有相同标识符的锁。
锁定服务的SQL接口实现了本节中描述的可加载函数。使用示例请参见使用锁定服务功能界面。
这些功能共享这些特征:
返回值为非零表示成功。否则,会出现错误。
命名空间和锁名称必须是非
空值
,非空,最大长度为64个字符。超时值必须是整数,表示在错误放弃之前等待获得锁的时间。如果timeout为0,则没有等待,如果不能立即获得锁,该函数将产生一个错误。
这些锁定服务功能可用:
service_get_read_locks(
名称空间
那lock_name.
[,lock_name.
] ......,超时
)使用给定的锁名称获取给定命名空间中的一个或多个读取(共享)锁定,如果未在给定的超时值内未获取锁定,则会出现错误。
service_get_write_locks (
名称空间
那lock_name.
[,lock_name.
] ......,超时
)使用给定的锁名在给定的命名空间中获取一个或多个写(排他)锁,如果在给定的超时值内没有获取锁,则超时并报错。
对于给定的命名空间,释放使用在当前会话中获取的所有锁定使用
service_get_read_locks ()
和service_get_write_locks ()
。命名空间中没有锁定是一个错误。