MySQL允许客户端会话显式地获取表锁,以便与其他会话协作访问表,或者防止其他会话在其需要独占表时使用表。这个能力就是通过LOCK TABLES和UNLOCK TABLES实现的。

LOCK TABLES用于显示的获取表锁,UNLOCK TABLES显式释放当前会话持有的任何表锁。

MySQL 5.7版本中它们的完整语法是:

LOCK TABLES

tbl_name [[AS] alias] lock_type

[, tbl_name [[AS] alias] lock_type] …

lock_type: {

READ [LOCAL]

| [LOW_PRIORITY] WRITE

}

UNLOCK TABLES

LOCK TABLES可以为基表或视图获取表锁。必须具有要锁定的每个对象的“LOCK TABLES”权限和“SELECT”权限。

不同的锁类型有不同的效果。

READ [LOCAL]锁:

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

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

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

加上LOCAL关键字,表示在持有锁的同时允许其它会话执行非冲突插入语句(并发插入)。但是,如果要在持有锁的同时使用外部进程操作数据库,则不能使用READ LOCAL。对于InnoDB表,READ LOCAL与READ相同。

会话1登入,并修改提示符包含session1字样,然后对emp表读取,可以进行,然后用lock tables给emp表加read锁定。

root@database-one 13:57: [(none)]> prompt \u@database-one \R:\m:\s [\d] session1>

PROMPT set to '\u@database-one \R:\m:\s [\d] session1>'

root@database-one 13:57:55 [(none)] session1>use gftest;

Database changed

root@database-one 13:58:31 [gftest] session1>select * from emp;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

+--------+------+---------+------------+--------+

5 rows in set (0.00 sec)

root@database-one 14:03:18 [gftest] session1>lock tables emp read;

Query OK, 0 rows affected (0.00 sec)

root@database-one 14:03:20 [gftest] session1>insert into emp values('陈实',31,9000,'2019-07-01',10);

ERROR 1099 (HY000): Table 'emp' was locked with a READ lock and can't be updated

可以看到,read锁定时只能读取,无法修改数据。

会话2登入,并修改提示符包含session2字样,然后对emp表读取。

root@database-one 14:04: [(none)]> prompt \u@database-one \R:\m:\s [\d] session2>

PROMPT set to '\u@database-one \R:\m:\s [\d] session2>'

root@database-one 14:05:04 [(none)] session2>use gftest;

Database changed

root@database-one 14:05:10 [gftest] session2>select * from emp;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

+--------+------+---------+------------+--------+

5 rows in set (0.00 sec)

root@database-one 14:05:20 [gftest] session2>lock tables emp read;

Query OK, 0 rows affected (0.00 sec)

可以看到,继续能够读取,同时也能加read锁。

[LOW_PRIORITY] WRITE锁:

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

只有持有锁的会话才能访问表。在释放锁之前,其他会话无法访问它。

当保持WRITE锁时,其他会话对表的锁请求被阻塞。

LOW_PRIORITY关键字已经作废。在以前的MySQL版本中,它影响锁定行为,但现在已经不是这样了。现在不推荐使用它,它的使用会产生一个警告。

会话1登入,并修改提示符包含session1字样,然后对emp表写入,可以进行,然后用lock tables给emp表加write锁定。

root@database-one 21:32: [(none)]> prompt \u@database-one \R:\m:\s [\d] session1>

PROMPT set to '\u@database-one \R:\m:\s [\d] session1>'

root@database-one 21:32:57 [(none)] session1>use gftest;

Database changed

root@database-one 21:33:07 [gftest] session1>select * from emp;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

+--------+------+---------+------------+--------+

5 rows in set (0.00 sec)

root@database-one 21:33:20 [gftest] session1>insert into emp values('陈实',31,9000,'2019-07-01',10);

Query OK, 1 row affected (0.01 sec)

root@database-one 21:34:50 [gftest] session1>lock tables emp write;

Query OK, 0 rows affected (0.00 sec)

会话2登入,并修改提示符包含session2字样,然后对emp表进行查询。

root@database-one 21:38: [(none)]> prompt \u@database-one \R:\m:\s [\d] session2>

PROMPT set to '\u@database-one \R:\m:\s [\d] session2>'

root@database-one 21:38:13 [(none)] session2>use gftest;

Database changed

root@database-one 21:38:21 [gftest] session2>select * from emp;

可以看到,表被以write方式锁定后,其它会话读取都无法进行,更不用提写入了。

UNLOCK TABLES显式释放当前会话持有的任何表锁。我们去session1中释放锁。

root@database-one 21:36:20 [gftest] session1>

root@database-one 21:45:29 [gftest] session1>unlock tables;

Query OK, 0 rows affected (0.00 sec)

root@database-one 21:45:43 [gftest] session1>

root@database-one 21:38:21 [gftest] session2>select * from emp;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

| 陈实 | 31 | 9000.00 | 2019-07-01 | 10 |

+--------+------+---------+------------+--------+

6 rows in set (7 min 11.08 sec)

root@database-one 21:45:43 [gftest] session2>

可以看到,session1在21:45:29后释放了锁,session2在21:45:43前就立即读取出了emp表的数据,整整排队等待了7分多钟,这些时间都被计入了这个SELECT的执行时间。

如果语句通过表名锁定,则不能使用别名。

root@database-one 21:57:54 [gftest] session1>lock table emp read;

Query OK, 0 rows affected (0.01 sec)

root@database-one 21:58:02 [gftest] session1>select * from emp as e;

ERROR 1100 (HY000): Table 'e' was not locked with LOCK TABLES

root@database-one 21:58:06 [gftest] session1>select * from emp;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

| 陈实 | 31 | 9000.00 | 2019-07-01 | 10 |

+--------+------+---------+------------+--------+

6 rows in set (0.00 sec)

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

root@database-one 22:00:54 [gftest] session1>unlock tables;

Query OK, 0 rows affected (0.00 sec)

root@database-one 22:01:23 [gftest] session1>

root@database-one 22:01:25 [gftest] session1>lock table emp as e read;

Query OK, 0 rows affected (0.00 sec)

root@database-one 22:01:30 [gftest] session1>select * from emp;

ERROR 1100 (HY000): Table 'emp' was not locked with LOCK TABLES

root@database-one 22:01:34 [gftest] session1>select * from emp as e;

+--------+------+---------+------------+--------+

| ename | age | sal | hiredate | deptno |

+--------+------+---------+------------+--------+

| 郭军 | 27 | 8400.00 | 2019-12-08 | 10 |

| 刘杰 | 30 | 9100.00 | 2018-04-09 | 10 |

| 王艳 | 24 | 6000.00 | 2020-01-05 | 20 |

| 马丽 | 26 | 7200.00 | 2018-07-06 | 30 |

| 肖伟 | 29 | 8700.00 | 2017-05-28 | 30 |

| 陈实 | 31 | 9000.00 | 2019-07-01 | 10 |

+--------+------+---------+------------+--------+

6 rows in set (0.00 sec)

会话可以显式释放其锁,或者在某些条件下隐式释放锁。

会话可以使用UNLOCK TABLES显式释放其锁。

如果会话已经持有锁,还发出LOCK TABLES语句来获取新锁,那么在授予新锁之前,现有锁将被隐式释放。

如果会话开始事务(例如,使用START transaction),则隐式执行UNLOCK TABLES,从而释放现有锁。

无论客户端会话的连接正常结束或异常终止,服务器均隐式释放该会话持有的所有表锁(事务性和非事务性)。

LOCK TABLES和UNLOCK TABLES与事务的交互如下:

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

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

FLUSH TABLES WITH READ LOCK;

START TRANSACTION;

SELECT ... ;

UNLOCK TABLES;

开始事务(例如,使用START transaction)隐式提交任何当前事务并释放现有表锁。

对事务表(如InnoDB TABLES)使用LOCK TABLES和UNLOCK TABLES的正确方法是,以SET autocommit=0(不是START transaction)后跟LOCK TABLES开始事务,并且在显式提交事务之前不调用UNLOCK TABLES。例如,如果需要写入表t1并读取表t2,可以执行以下操作:

SET autocommit=0;

LOCK TABLES t1 WRITE, t2 READ, ...;

... do something with tables t1 and t2 here ...

COMMIT;

UNLOCK TABLES;

ROLLBACK不会释放表锁。

综上所述,当我们需要独占式的对表做一些运维操作时,使用LOCK TABLES和UNLOCK TABLES是个很不错的选择。

lock mysql unlock_MySQL中的lock tables和unlock tables相关推荐

  1. lock mysql unlock_MySql中Lock命令和unlock命令

    在同一個連接當中,執行了一次lock table之后,如果再次執行lock table,那么之前被鎖住的表就自動解鎖了. 下面這張圖可以證明: ---------------------------- ...

  2. lock字段mysql_MySQL的lock tables和unlock tables的用法(转载)

    早就听说lock tables和unlock tables这两个命令,从字面也大体知道,前者的作用是锁定表,后者的作用是解除锁定.但是具体如何用,怎么用,不太清楚.今天详细研究了下,总算搞明白了2者的 ...

  3. mysql中lock tables与unlock tables(锁表/解锁)

    在某个地方看到有个例子,具体描述类似如下:商店现在某商品只有1件库存,然后A与B在网上进行下订,A与B几乎同时(或许也就差几毫秒,A比B快那么一点点)进行. 很明显是只有A才能成功下单的,B则会收到库 ...

  4. mysql关于FLUSH TABLES和FLUSH TABLES WITH READ LOCK的理解

    总结 1.FLUSH TABLES关闭所有打开的表,强制关闭所有正在使用的表,并刷新查询缓存和预准备语句缓存,不会刷新脏块 2.FLUSH TABLES WITH READ LOCK关闭所有打开的表并 ...

  5. mysql中flush tables和flush tables with read lock详解

    官方手册中关于Flush tables的介绍, Closes all open tables, forces all tables in use to be closed, and flushes t ...

  6. MySQL笔记-InnoDB中Record Lock与Gap Lock

    锁:用于在多个事务访问同一个对象时根据这些操作访问同一对象的先后次序给事务排序. 不同数据库的锁实现: InnoDB:行级锁: Oracle:行级锁: MyISAM:表级锁: Microsoft SQ ...

  7. C++中的Lock简单用法

    简单记录一下C++中的Lock的用法 下面是使用临界区进行线程同步 首先定义一个临界区对象 CCriticalSection m_CritSect; //临界对象,同步线程使用 在需要使用到可能起冲突 ...

  8. [译] 理解 NPM 5 中的 lock 文件

    本文讲的是[译] 理解 NPM 5 中的 lock 文件, 原文地址:Understanding lock files in NPM 5 原文作者:Jiří Pospíšil 译文出自:掘金翻译计划 ...

  9. NET面试题:C#中的lock关键字有何作用

    NET面试题:C#中的lock关键字有何作用 2011-03-01 08:42:04 标签:.net面试题 .net电子书 .net教学视频 .net 更多.net面试题,.net电子书,.net教学 ...

最新文章

  1. python实现洗牌算法_为什么渔民耶茨最有用的洗牌算法?
  2. session过期设置
  3. Ubuntu文件压缩、解压缩、打包
  4. Linux文本编辑器之vim
  5. 由于供不应求 部分新款Apple Watch机型推迟至11月交付
  6. 我的世界服务器怎么弄无限急迫,我的世界有什么指令设置无限急迫
  7. 倾心家教安卓案例开发代码_你或许从未听过的20个安卓开发工具
  8. linux怎么编译python_linux 编译安装python3
  9. Mathtype6.9保姆级安装教程,亲测可用-----经常踩坑
  10. 收款码三合一生成系统源码
  11. LittleVGL开发之显示中文字体以及矢量图标
  12. Win11如何查看硬盘型号?Win11查看硬盘型号步骤
  13. 实验三mysql查询_实验三 数据库的查询实验
  14. DRM dumb,prime介绍
  15. 深入浅出LSTM学习
  16. magic2怎样升级HarmonyOS,鸿蒙2.0怎么升级 华为鸿蒙新系统升级方法步骤
  17. W3150A+评估板--EVB-PIC24用户手册(四)硬件设计指南
  18. vscode透明主题、霓虹灯字体
  19. 外包新政策或年底出台
  20. D3js-绘制SVG

热门文章

  1. Java 8中的HashMap性能改进
  2. PrimeFaces在GlassFish 3.1.2.2上推动大气
  3. 使用JAXB从XSD生成XML
  4. 具有Java 7中自动资源管理功能的GC
  5. Java编程中如何获取项目文件的路径/文件路径
  6. Xenix — 微软与UNIX的短暂爱恋
  7. mysql注入漏洞语句,web安全之sql注入漏洞
  8. mvc 404错误 php,java - springmvc 请求无法到达controller,出现404错误
  9. linux 4.1.16 ftrace 进程调度,Linux内核进程调度overview(1)
  10. hpux oracle9,oracle 9.2.0.8在HP-UX 11.31 下的安装步骤和注意事项