zoukankan      html  css  js  c++  java
  • LOCK TABLES and UNLOCK TABLES

    LOCK TABLES
        tbl_name [[AS] alias] lock_type
        [, tbl_name [[AS] alias] lock_type] ...
    
    lock_type: {
        READ [LOCAL]
      | [LOW_PRIORITY] WRITE
    }
    
    UNLOCK TABLES

    MySQL使客户端会话能够显式地获取表锁,以便与其他会话协作访问表,或者防止其他会话在会话需要互斥访问期间修改表。会话只能为其自身获取或释放锁。一个会话无法获取另一会话的锁,也不能释放另一会话持有的锁。

    在更新表时,锁可用于模拟事务或提高速度。

    如果使用显式锁定LOCK TABLES,则触发器中使用的任何表也会隐式锁定.

    UNLOCK TABLES显式释放当前会话持有的所有表锁。 在获取新锁之前,隐式释放当前会话持有的所有表锁。

    UNLOCK TABLES的另一种用法是释放通过该FLUSH TABLES WITH READ LOCK 语句获取的全局读取锁定,这使您可以锁定所有数据库中的所有表。

    表锁只能防止其他会话进行不适当的读取或写入。持有WRITE 锁的会话可以执行表级操作,例如 DROP TABLE或 TRUNCATE TABLE对于持有会话READ锁,DROP TABLETRUNCATE TABLE 操作是不允许的。

    以下讨论仅适用于非TEMPORARY表。LOCK TABLES允许(但忽略) TEMPORARY表。

    在当前会话中获取表锁,使用 LOCK TABLES 语句

    READ [LOCAL] 锁:

      持有锁的会话可以读取表(但不能写入表)。

      多个会话可以同时获取该表的READ锁。

      其他会话可以在不显式获取READ锁的情况下读取表

      使用LOCAL可以在并发插入时不产生冲突。

      但是,如果您要在持有READ LOCAL锁的同时使用服务器外部的进程来操作数据库, 则不能使用它。对于 InnoDB表,READ LOCAL与READ相同

    [LOW_PRIORITY] WRITE 锁:

      持有锁的会话可以读写表。

      只有持有锁的会话才能访问该表。在释放锁之前,没有其他会话可以访问它。

      保持WRITE锁定状态时,其他会话对表的锁定请求将阻塞

      LOW_PRIORITY修饰符无效。在以前的MySQL版本中,它影响了锁定行为,但现在不再如此。现在已弃用,使用它会产生警告。使用WRITE不带 LOW_PRIORITY

    需要锁的会话必须在单个锁表语句中获取所需的所有锁。当这样获得的锁被持有时,会话只能访问锁定的表。例如,在以下语句序列中,尝试访问t2时出错,因为t2在LOCK TABLES语句中未被锁定:

    mysql> LOCK TABLES t1 READ;
    mysql> SELECT COUNT(*) FROM t1;
    +----------+
    | COUNT(*) |
    +----------+
    |        3 |
    +----------+
    mysql> SELECT COUNT(*) FROM t2;
    ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES

    不能在同一个查询中使用相同的名称多次引用锁定的表。请改用别名,并为表和每个别名获取单独的锁:

    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;

    如果您的语句通过别名引用表,则必须使用相同的别名锁定表。如果不指定别名,则无法锁定表:

    mysql> LOCK TABLE t READ;
    mysql> SELECT * FROM t AS myalias;
    ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

    相反,如果使用别名锁定表,则必须在该语句中使用该别名引用该表:

    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;

    表锁定和事务的交互

    LOCK TABLES UNLOCK TABLES与事务进行交互,如下所示:

      LOCK TABLES 不是事务安全的,而是在尝试锁定表之前隐式提交任何活动事务。

      UNLOCK TABLES隐式提交任何活动事务,但前提是LOCK TABLES已用于获取表锁。例如,在以下语句集中, UNLOCK TABLES释放全局读取锁,但由于没有有效表锁,因此不提交事务:

    FLUSH TABLES WITH READ LOCK;
    START TRANSACTION;
    SELECT ... ;
    UNLOCK TABLES;

    开始事务(例如,使用START TRANSACTION),会隐式提交任何当前事务,并释放存在的表锁。

    FLUSH TABLES WITH READ LOCK 获得全局读锁定,而不是表锁,所以不会受到像 LOCK TABLES and UNLOCK TABLES关于表锁定和隐式提交一样的约束,例如, START TRANSACTION不会释放全局读锁。

    其他隐式导致事务提交的语句不会释放现有的表锁。

    在事务表中正确的使用lock tables 和 unlock tables ,比如innodb 表,一个事务开始用SET  autocommit=0(而不是start transaction) 后面跟着 lock tables,最后直到显示的提交commit后,才可以使用unlock tables.比如,你需要写表t1和读表t2,可以如下:

    SET autocommit=0;
    LOCK TABLES t1 WRITE, t2 READ, ...;
    ... do something with tables t1 and t2 here ...
    COMMIT;
    UNLOCK TABLES;

    当你用lock tables时,innodb 使用它自己内部的表锁,MYSQL使用它自己的表锁。在提交时innodb释放它内部的表锁,但是对于MYSQL,必须使用UNLOCK TABLES才会释放它的锁。不能设置autocommit=1,因为这样在lock tables 后,innodb会立即释放它的内部表锁,容易发生死锁。如果autocommit=1,innodb不会一直要求内部表锁,是为了帮助老的应用避免非必要的死锁。

    ROLLBACK不会释放表锁。

  • 相关阅读:
    UVa532 Dungeon Master 三维迷宫
    6.4.2 走迷宫
    UVA 439 Knight Moves
    UVa784 Maze Exploration
    UVa657 The die is cast
    UVa572 Oil Deposits DFS求连通块
    UVa10562 Undraw the Trees
    UVa839 Not so Mobile
    327
    UVa699 The Falling Leaves
  • 原文地址:https://www.cnblogs.com/wonchaofan/p/13521240.html
Copyright © 2011-2022 走看看