赞
踩
LOCK TABLES 和 UNLOCK TABLES 语句
1. LOCK TABLES
2. tbl_name [[AS] alias] lock_type
3. [, tbl_name [[AS] alias] lock_type] ...
4.
5. lock_type: {
6. READ [LOCAL]
7. | [LOW_PRIORITY] WRITE
8. }
9.
10. UNLOCK TABLES
MySQL 允许客户端会话显式获取表锁,以便与其他会话协作访问表,或者在会话需要独占访问表时阻止其他会话修改表。会话只能获取或释放自身的锁。一个会话无法获取另一个会话的锁或释放另一个会话持有的锁。
锁可用于模拟事务或在更新表时获得更快的速度。
LOCK TABLES 显式获取当前客户端会话的表锁。可以对基本表或视图获取表锁定。要锁定对象,必须具有对象的 LOCK TABLES 权限和 SELECT 权限。
对于视图锁定,LOCK TABLES 将视图中使用的所有基本表添加到要锁定的表集合中,并自动锁定它们。对于被锁定的任何视图的底层表,LOCK TABLES 检查视图定义者(SQL SECURITY DEFINER 视图)或调用者(所有视图)是否对表具有适当的权限。
如果使用 LOCK TABLES 显式锁定表,则触发器中使用的任何表也将隐式锁定。
如果使用 LOCK TABLES 显式锁定表,则任何与外键约束相关的表都将被隐式打开和锁定。对于外键检查,对相关表使用共享只读锁(LOCK TABLES READ)。对于级联更新,对操作中涉及的相关表执行无共享的写入锁(LOCK TABLES WRITE)。
UNLOCK TABLES 显式释放当前会话持有的所有表锁。LOCK TABLES 在获取新锁之前隐式释放当前会话持有的所有表锁。
UNLOCK TABLES 的另一个用途是释放用 FLUSH TABLES WITH READ LOCK 语句获取的全局读锁,它能够锁定所有数据库中的所有表。(如果您的文件系统(如 Veritas)可以及时获取快照,则这是一种非常方便的备份方法。)
表锁只保护其他会话的不适当的读写操作。持有 WRITE 锁的会话可以执行诸如 DROP TABLE 或 TRUNCATE TABLE 之类的表级操作。对于持有 READ 锁的会话,不允许执行 DROP TABLE 和 TRUNCATE TABLE 操作。
以下讨论仅适用于非临时表。对于临时表,允许(但忽略)LOCK TABLES 语句。表可以由创建它的会话自由访问,无论其他什么锁定在生效。其实根本无需锁定,因为没有其他会话可以看到该表。
表锁的获取
要在当前会话中获取表锁定,请使用 LOCK TABLES 语句,该语句将获取元数据锁。
以下锁类型可用:
READ [LOCAL] 锁定:
● 持有锁的会话可以读取表(但不能写表)。
● 多个会话可以同时获取表的 READ 锁。
● 其他会话可以在不显式获取 READ 锁的情况下读取表。
● LOCAL 修饰符使其他会话的非冲突 INSERT 语句(并发插入)能够在保持锁的同时执行。但如果要在持有锁的同时使用服务器外部的进程操作数据库,则不能使用 READ LOCAL。对于 InnoDB 表,READ LOCAL 与 READ 相同。
[LOW_PRIORITY] WRITE 锁定:
● 持有锁的会话可以读写表。
● 只有持有锁的会话才能访问表。在释放锁之前,没有其他会话可以访问它。
● 当保持 WRITE 锁时,其他会话对表的锁定请求将被阻止。
● LOW_PRIORITY 修饰符无效。在以前版本的 MySQL 中,它影响锁定行为,但现在不再是这样了。它现在已被弃用,使用它会产生警告。请改用不带 LOW_PRIORITY 的 WRITE。
WRITE 锁通常比 READ 锁具有更高的优先级,以确保尽快处理更新。这意味着,如果一个会话获得一个 READ 锁,然后另一个会话请求一个 WRITE 锁,那么后续的 READ 锁请求会一直等到请求 WRITE 锁的会话获得并释放了锁。(对于 max_write_lock_count 系统变量的较小值,可能会出现此策略的例外。)
如果由于任何表上的其他会话持有锁,LOCK TABLES 语句必须等待,那么它将阻塞,直到可以获取所有锁。
需要锁的会话必须在单个 LOCK TABLES 语句中获取所需的所有锁。当这样获得的锁被持有时,会话只能访问锁定的表。例如,在以下语句序列中,尝试访问 t2 时出错,因为 t2 在 LOCK TABLES 语句中未被锁定:
1. mysql> LOCK TABLES t1 READ;
2. mysql> SELECT COUNT(*) FROM t1;
3. +----------+
4. | COUNT(*) |
5. +----------+
6. | 3 |
7. +----------+
8. mysql> SELECT COUNT(*) FROM t2;
9. ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
INFORMATION_SCHEMA 数据库中的表是一个例外。即使有会话持有通过 LOCK TABLES 获得的表锁,也可以在不显式锁定的情况下访问它们。
不能在同一个查询中使用相同的名称多次引用锁定的表。使用别名代替,并为表和每个别名获得一个单独的锁:
1. mysql> LOCK TABLE t WRITE, t AS t1 READ;
2. mysql> INSERT INTO t SELECT * FROM t;
3. ERROR 1100: Table 't' was not locked with LOCK TABLES
4. mysql> INSERT INTO t SELECT * FROM t AS t1;
第一个 INSERT 语句出错,因为对锁定的表有两个同名引用。第二个 INSERT 成功,因为对表的引用使用不同的名称。
如果语句通过别名引用表,则必须使用同一别名锁定表:
1. mysql> LOCK TABLE t READ;
2. mysql> SELECT * FROM t AS myalias;
3. ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
相反,如果使用别名锁定表,则必须在语句中使用该别名引用表:
1. mysql> LOCK TABLE t AS myalias READ;
2. mysql> SELECT * FROM t;
3. ERROR 1100: Table 't' was not locked with LOCK TABLES
4. mysql> SELECT * FROM t AS myalias;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。