锁表tbl_name[[是]别名]lock_type[,tbl_name[[是]别名]lock_type)……lock_type: {read [local] | [low_priority] write}解锁表
MySQL允许客户端会话显式地获取表锁,以便与其他会话合作访问表,或者防止其他会话在会话需要独占访问表期间修改表。会话只能为自己获取或释放锁。一个会话不能为另一个会话获取锁,也不能释放另一个会话持有的锁。
锁可以用来模拟事务,或者在更新表时提高速度。这将在表锁定限制和条件.
锁表
显式地为当前客户端会话获取表锁。可以为基表或视图获取表锁。你必须有锁表
特权,选择
每个被锁定对象的特权。
为视图锁定,锁表
将视图中使用的所有基表添加到要锁定的表集中,并自动锁定它们。对于任何被锁定视图的底层表,锁表
检查视图定义器(forSQL安全定义者
视图)或调用程序(对于所有视图)对表具有适当的特权。
如果显式地锁定表锁表
,触发器中使用的任何表也会隐式锁定,如中所述锁表和触发器.
如果显式地锁定表锁表
,任何与外键约束相关的表都将隐式打开和锁定。对于外键检查,共享只读锁(锁表读
)在相关表上。对于级联更新,无共享写锁(锁表写
)被取到与操作相关的表上。
打开表
显式释放当前会话持有的任何表锁。锁表
在获取新锁之前隐式释放当前会话持有的任何表锁。
另一个使用打开表
方法获取的全局读锁是否释放用读锁刷新表
语句,该语句使您能够锁定所有数据库中的所有表。看到第13.7.8.3节," FLUSH语句".(如果您有一个文件系统,如Veritas,可以及时进行快照,这是一种非常方便的获取备份的方法。)
表锁只保护其他会话不适当的读或写。举行会议的会议写
Lock可以执行表级操作,例如删除表
或截断表
.举行读
锁,删除表
而且截断表
禁止操作。
下面的讨论只适用于非临时
表。锁表
是否允许(但被忽略)临时
表格该表可以由创建它的会话自由访问,而不管其他锁是否有效。不需要锁,因为没有其他会话可以看到该表。
要获取当前会话中的表锁,请使用锁表
语句,该语句获取元数据锁(参见第8.11.4节“元数据锁定”).
有以下几种锁类型:
读(本地)
锁:
持有锁的会话可以读表(但不能写表)。
多个会话可以获得一个
读
同时锁定表。其他会话可以读取表而不显式地获取
读
锁。的
当地的
修饰符可以不冲突插入
语句(并发插入),以便在持有锁时执行。(见第8.11.3节“并发插入”)。然而,阅读当地
如果您打算在持有锁的同时使用服务器外部的进程操作数据库,则不能使用该选项。为InnoDB
表,阅读当地
和读
.
(LOW_PRIORITY)写
锁:
持有锁的会话可以读写表。
只有持有锁的会话才能访问该表。在释放锁之前,没有其他会话可以访问它。
其他会话对表的锁定请求被阻塞
写
锁举行。的
LOW_PRIORITY
修饰符无效。在以前版本的MySQL中,它会影响锁定行为,但现在不再是这样了。现在已弃用,使用它会产生警告。使用写
没有LOW_PRIORITY
代替。
写
锁的优先级通常高于读
锁定,以确保尽快处理更新。这意味着如果一个会话获得一个读
锁定,然后另一个会话请求写
锁,随后读
锁请求等待直到请求的会话写
Lock获得了锁并释放了锁。的小值可能会出现此策略的异常max_write_lock_count
系统变量;看到第8.11.4节“元数据锁定”)。
如果锁表
语句必须等待,因为任何表上的其他会话持有锁,它会阻塞,直到所有锁都被获取。
需要锁的会话必须在一个单独的会话中获得它需要的所有锁锁表
声明。当获得的锁被持有时,会话只能访问锁定的表。例如,在以下语句序列中,尝试访问时会发生错误t2
因为它没有锁在锁表
声明:
mysql>锁表SELECT COUNT(*) FROM t1;+----------+ | 数 (*) | +----------+ | 3 | +----------+ 从t2 mysql > SELECT COUNT (*);错误1100 (HY000):表“t2”没有锁定锁定表
表INFORMATION_SCHEMA
数据库是一个例外。可以在不显式锁定的情况下访问它们,甚至在会话持有通过获取的表锁时也是如此锁表
.
不能在一个查询中使用相同的名称多次引用一个锁定表。使用别名代替,并为表和每个别名获得一个单独的锁:
mysql>锁表t写,t为t1读mysql> INSERT INTO t SELECT * FROM t;Table 't' was not locked with LOCK TABLES mysql> INSERT INTO t SELECT * FROM t AS t1;
错误发生在第一个插入
因为对于一个锁定的表,有两个对相同名称的引用。第二个插入
成功是因为对表的引用使用了不同的名称。
如果语句通过别名引用表,则必须使用相同的别名锁定表。如果不指定别名,锁定表是无效的:
mysql>锁表SELECT * FROM t AS myalias;错误1100:表“myalias”没有被锁定
相反,如果你使用别名锁定一个表,你必须在你的语句中使用该别名引用它:
mysql>锁表mysql> SELECT * FROM;Table 't' was not locked with LOCK TABLES mysql> SELECT * FROM t AS myalias;
当会话持有的表锁被释放时,它们将同时被释放。会话可以显式释放锁,也可以在某些条件下隐式释放锁。
如果客户机会话的连接终止(正常或异常),服务器将隐式释放会话持有的所有表锁(事务性和非事务性)。如果客户端重新连接,锁将不再有效。此外,如果客户端有一个活动的事务,服务器将在断开连接时回滚该事务,如果发生重新连接,则新会话将开始并启用自动提交。因此,客户端可能希望禁用自动重新连接。在自动重新连接生效的情况下,如果发生重新连接,但丢失了任何表锁或当前事务,则不会通知客户机。在禁用自动重新连接的情况下,如果连接断开,发出的下一条语句将出错。客户机可以检测到错误并采取适当的操作,如重新获取锁或重新执行事务。看到自动重新连接控制.
如果你使用ALTER TABLE
在上锁的桌子上,它可能会变成无锁的。例如,如果你尝试第二次ALTER TABLE
操作时,结果可能是错误表的
.要处理这个问题,请在第二次修改之前再次锁定表。另请参阅B.3.6.1节“ALTER TABLE的问题”.tbl_name
'不是锁表
锁表
不是事务安全的,并且在试图锁定表之前隐式提交任何活动事务。打开表
隐式提交任何活动事务,但只有在锁表
已经被用来获取表锁。例如,在下面这组语句中,打开表
释放全局读锁但不提交事务,因为没有表锁生效:用读锁刷新表;开始事务;选择……;打开表;
开始事务(例如,与
开始事务
)隐式提交任何当前事务并释放现有的表锁。用读锁刷新表
获取全局读锁而不是表锁,因此它不受制于与锁表
而且打开表
关于表锁定和隐式提交。例如,开始事务
不释放全局读锁。看到第13.7.8.3节," FLUSH语句".其他隐式导致事务提交的语句不会释放现有的表锁。有关此类语句的列表,请参见第13.3.3节“导致隐式提交的语句”.
正确的使用方法
锁表
而且打开表
使用事务表,例如InnoDB
表,是用来开始交易的SET autocommit = 0
(不开始事务
)紧随其后锁表
和不要打电话打开表
直到您显式地提交事务。例如,如果您需要写入表t1
从表格中读取t2
,你可以这样做:设置自动提交= 0;锁表t1写,t2读,…...在这里对表t1和t2做一些事情……提交;打开表;
当你打电话
锁表
,InnoDB
internal使用它自己的表锁,MySQL使用它自己的表锁。InnoDB
在下一次提交时释放它的内部表锁,但是MySQL要释放它的表锁,你必须调用打开表
.你不应该自动提交= 1
,因为这样InnoDB
的调用后立即释放其内部表锁锁表
,死锁很容易发生。InnoDB
是否根本没有获得内部表锁自动提交= 1
,以帮助旧应用程序避免不必要的死锁。回滚
不释放表锁。
如果显式地锁定表锁表
,触发器中使用的任何表也会被隐式锁定:
假设您锁定了两个表,t1
而且t2
,使用以下语句:
锁表t1写,t2读;
如果t1
或t2
如果有任何触发器,那么在触发器中使用的表也会被锁定。假设t1
触发器的定义如下:
CREATE TRIGGER t1_a_ins AFTER INSERT ON t1 FOR EACH ROW BEGIN UPDATE t4 SET count = count+1 WHERE id = NEW。id AND EXISTS (SELECT a FROM t3);INSERT INTO t2 VALUES(1,2);结束;
的结果锁表
声明是t1
而且t2
被锁定是因为它们出现在对账单中,然后t3
而且t4
被锁定是因为它们在触发器中使用:
t1
是否锁定用于写入写
锁请求。t2
为写入锁定,即使请求是针对读
锁。这是因为t2
被插入到触发器中,因此读
请求转换为写
请求。t3
锁定用于读取,因为它只从触发器内部读取。t4
为写入锁定,因为它可能在触发器内更新。
你可以安全地使用杀了
终止正在等待表锁的会话。看到第13.7.8.4节,“KILL语句”.
表performance_schema
数据库无法锁定锁表
,除了setup_
表。xxx
当a锁表
声明生效:创建表
,创建表……就像
,创建视图
,删除视图
,以及关于存储函数和过程和事件的DDL语句。
中的系统表对于某些操作mysql
必须访问数据库。例如,帮助
语句需要服务器端帮助表的内容,并且CONVERT_TZ ()
可能需要读取时区表。服务器隐式地锁定系统表以便在必要时读取,因此您不需要显式地锁定它们。这些表的处理方法如下:
mysql。help_category mysql。help_keyword mysql。help_relation mysql。help_topic mysql。time_zone mysql。time_zone_leap_second mysql。time_zone_name mysql。time_zone_transition mysql.time_zone_transition_type
如果你想显式地放置a写
锁定任何一个表锁表
语句中,表必须是唯一锁定的表;没有其他表可以用相同的语句锁定。
通常,您不需要锁定表,因为所有表都是单表更新
语句是原子;任何其他会话都不能干扰其他正在执行的SQL语句。然而,在一些情况下,锁定表可能会提供优势:
如果你要在一组上运行许多操作
MyISAM
表,锁定将要使用的表要快得多。锁定MyISAM
表的插入、更新或删除速度加快,因为MySQL不会刷新锁定表的键缓存,直到打开表
被称为。通常,键缓存在每个SQL语句之后被刷新。锁定表的缺点是没有会话可以更新
读
表(包括持有锁的表),没有会话可以访问写
除了拿着锁的那张表。如果为非事务性存储引擎使用表,则必须使用
锁表
如果您想确保没有其他会话修改a之间的表选择
和一个更新
.这里显示的示例需要锁表
执行安全:锁表反读,客户写;SELECT SUM(value) FROM trans WHERE customer_id=some_id;更新客户SET total_value=sum_from_previous_statementcustomer_id =some_id;打开表;
你可以避免使用锁表
在许多情况下,通过使用相对更新(更新客户组
)或价值
=价值
+new_value
LAST_INSERT_ID ()
函数。
在某些情况下,还可以通过使用用户级建议锁函数来避免锁定表GET_LOCK ()
而且RELEASE_LOCK ()
.这些锁保存在服务器的散列表中,并使用pthread_mutex_lock ()
而且pthread_mutex_unlock ()
高速度。看到第12.15节,“锁定功能”.
看到第8.11.1节“内部锁定方法”,以了解有关锁定策略的更多信息。