暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的SQL语句 -事务性语句和锁定语句(5)- LOCK TABLES 和 UNLOCK TABLES 语句(1)

数据库杂货铺 2021-04-12
332
LOCK TABLES 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 显式获取当前客户端会话的表锁。可以对基本表或视图获取表锁定。要锁定对象,必须具有对象的 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 语句中未被锁定:
     
      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
       
      INFORMATION_SCHEMA 数据库中的表是一个例外。即使有会话持有通过 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;
         
        第一个 INSERT 语句出错,因为对锁定的表有两个同名引用。第二个 INSERT 成功,因为对表的引用使用不同的名称。
         
        如果语句通过别名引用表,则必须使用同一别名锁定表:
         
          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;
             
             
             
            官方网址:
            https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html
             

            文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论