14.3.5 LOCK TABLES and UNLOCK TABLES Syntax
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type:
READ [LOCAL]
| [LOW_PRIORITY] WRITE
UNLOCK TABLES
MySQL让客户端sessions 获得表锁明确的用于配合其他会话访问表,或者阻止其他会话修改表 在一个session
需要排它访问它们时。一个session可以获得或者释放它自己的锁。
一个会话不能获得锁对于其他会话或者释放被其他会话持有的锁。
锁可以用于模拟事务或者得到更快的速度当更新表时, 这在本节中有更详细的解释:
LOCK TABLES 显示的获得表锁用于当前客户端session,Tables locks 可以获得对于基表或者视图。
你必须有LOCK TABLES的权限,SELECT 权限对于每个被锁定的对象。
对于视图locking,LOCK TABLES 增加所有视图里的所有基表 到表集合被锁定,自动锁定它们。
如果你明确的lock 一个表 使用LOCK TABLES,任何表用于触发器的也会被锁定。
UNLOCK TABLES 显示的释放任何表的锁 被当前会话持有的。
LOCK TABLES 隐式的释放任何被当前会话持有的锁 在获得新的锁前
另外使用UNLOCK TABLES 是释放global read lock 通过FLUSH TABLES WITH READ LOCK语句获得,
让你lock 所有数据库的所有表
一个table lock只保护不合适的写和读通过其他会话。一个会话持有一个WRITE LOCK 可以执行表级操作
比如DROP TABLE or TRUNCATE TABLE.
下面的讨论只 应用于 non-TEMPORARY tables.
LOCK TABLES 是被允许的对对于一个 TEMPORARY table.
表可以被*访问 通过session,无论什么其他的锁可能生效,No lock 是需要的 因为其他会话看不到表。
锁定获取规则:
获得表锁 在当前会话,使用LOCK TABLES 语句,下面lock types 是可用的:
READ [LOCAL] lock:
1.session 持有锁可以read表但是不能写
2.多个会话可以获得一个READ lock 对于一个表在同一时间
3.其他会话可以读表,而无需显示地获取READ lock.
4.LOCAL 修饰符让非冲突的INSERT语句(并发inserts)通过其他会话执行,当锁被持有时。
然而, READ LOCAL 不能被使用如果你是处理数据库使用处理外部到servver 当你持有锁时,
对于InnoDB,READ LOCAL is the same as READ.
低优先级 WRITE lock:
1. session 持有lock 可以读和写表
2.只有session 持有lock 可以访问表,其他session 不能访问表知道lock被释放
3.Lock 请求对于表通过其他会话 会被堵塞 当WRITE lock被持有
4.LOW_PRIORITY 修饰符没有作用,它是MYSQL以前的版本
如果LOCK TABLES 语句必须等待由于lock被其他会话持有,它被堵塞直到所有的locks 可以被获取
一个会话需要获得locks 必须获得所有的locks 需要一个单独的LOCK TABLES 语句。
当locks 因此得到是被保持, session 可以只可以访问被锁定的表。例子,下面的语句的顺序,
一个错误发生对于尝试访问t2,因为不是被锁定的 在LOCK TABLES 语句。
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> lock table test read;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| NULL | a |
| 2 | b |
| 3 | c |
| 1 | a0101 |
| 4 | a |
| 4 | a |
| 5 | c |
| 10 | aa |
| 10 | aa |
+------+-------+
9 rows in set (0.00 sec)
mysql> select * from xx;
ERROR 1100 (HY000): Table 'xx' was not locked with LOCK TABLES
mysql> select user,host from mysql.user;
ERROR 1100 (HY000): Table 'user' was not locked with LOCK TABLES
表在INFORMATION_SCHEMA 是一个例外, 它们可以摆访问不需要被明确的锁定,即使当一个会话持有表locks 通过lock tables.
你不能指向一个locked table 多次 在一个单独的查询 使用相同的名字,使用别名代替,得到一个单独的多对于表和每个别名
mysql> LOCK TABLE t WRITE, t AS t1 READ;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;
第一个插入的错误发生 ,因为有2个引用到相同的表 对于一个锁定的表。
第2个INSERT 成功因为 引用到表使用不同的名字
如果你的语句指向一个表通过一个别名,你必须lock table 使用相同的alias.
它不会锁定表不指定别名
mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
相反,如果你lock一个表使用一个alias,你必须指向它在你的语句使用alais:
mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;
WRITE 锁通常有更好的优先级相比READ locks 来确保更新是尽可能快的处理。
这意味着如果一个session 得到一个READ lock 和然后其他的session 请求一个WRITE lock,
随后的READ lock 请求等待直到session 请求到的WRITE lock已经得到lock
lock tabls 需要locks如下:
1.排序所有的tables 被锁定在一个内部定义的顺序,从用户角度看,这个顺序是不确定的。
2.如果表是被锁定使用一个read 和一个write lock,放置write lock 请求在read lock 请求前
3.锁定一个表一次 直到会话得到所有的locks
锁释放规则:
当一个table locks 被一个会话持有被释放,它们都被释放在相同的时间。
一个session 可以释放它自己的锁,或者locks 可以被影式释放。
1.一个session 可以显示的释放它的锁
2. 如果一个会话执行一个LOCK TABLES 语句来获得一个Lock当已经被持有了,
它的存在的锁会被隐式的释放 在新的锁被授予前
如果一个会话开始一个事务(比如, 使用START TRANSACTION),一个隐式的UNLCOK TABLES是被执行,
会导致存在的表的锁被释放
mysql> lock table test read;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(99,'aqs');
ERROR 1099 (HY000): Table 'test' was locked with a READ lock and can't be updated
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(99,'aqs');
Query OK, 1 row affected (0.00 sec)