• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

MySQL表锁定(Table Locking)

MySQL 彭东稳 7年前 (2018-06-07) 22486次浏览 已收录 0个评论

MySQL允许客户端会话显式获取表锁,以防止其他会话在特定时间段内访问表。客户端会话只能为自己获取或释放表锁。它无法获取或释放其他会话的表锁。

在详细讨论之前,我们将创建一个名为示例的数据库sbtest,其中包含一个名为tbl实践表锁定语句的简单表。

一、LOCK和UNLOCK TABLES

LOCK TABLE的简单语法形式如下:

MySQL提供了两种锁类型:READ和WRITE,下面介绍。

要释放表的锁定,请使用以下语句:

二、表锁为READ类型

READ锁具有以下功能:

  • 一个表的READ锁可以同时被多个会话获取。另外,其他会话可以从表中读取数据而不需要获取锁。
  • 保存READ锁的会话只能从表中读取数据,但不能写入。另外,其他会话在READ锁定释放之前不能将数据写入表中。来自另一个会话的写入操作将被置于等待状态,直到READ锁定被释放。
  • 如果会话正常或异常终止,MySQL将隐式释放所有锁,WRITE锁也是如此。

让我们来看看READ锁在以下场景中的工作方式。

首先,连接到sbtest数据库。要找出当前的连接ID,可以使用CONNECTION_ID()函数:

然后,在tbl表中插入一个新行。

之后,要获得一个锁,你可以使用LOCK TABLE语句。

看一下此时表打开的情况。

最后,在同一个会话中,如果你尝试向表中插入新行,你将收到错误消息。

再来看看同一个会话中查询是否正常。

因此,获取一次READ锁定后,你无法在同一个会话中将数据写入表中。然后再来检查来自不同会话的READ锁。

首先,连接sbtest并检查连接ID:

然后,查询tbl表数据。

接下来,tbl从第二个会话中插入一个新行到表中。

来自第二个会话的插入操作处于等待状态,因为第一个会话已经在tbl表上获取了一个READ锁并且它尚未释放。

你可以从SHOW PROCESSLIST中看到详细的元数据锁等待信息。

 

之后,回到第一个会话并使用UNLOCK TABLES语句释放锁(或者中断第一个会话也会释放锁)。从第一个会话释放READ锁后,第二个会话中的INSERT操作将会立即执行成功。

lock tables有一个local关键字,如lock tables tbl read local,意思就是只针对当前会话加read锁。其他会话可以正常写入数据的,但是只能针对非InnoDB存储引擎才有效,对于InnoDB存储引擎无效。

最后还有一个小问题,其它会话能否也能给该表加LOCK TABLES READ? 其它会话是否也能给该表加LOCK TABLES WRITE?

结果表明,其他会话可以加LOCK TABLES READ,但不能加LOCK TABLES WRITE。

三、表锁为WRITE类型

WRITE的表锁具有以下功能:

  • 只有拥有表锁的会话才能读取和写入表中的数据,且可以删除表,但不能执行RENAME操作。
  • 在写入锁定被释放之前,其他会话不能读取和写入数据到表。

我们来详细了解WRITE锁的工作原理。

首先,从第一次会话中获取一个WRITE锁。

然后,在tbl表中插入一个新行。

虽然写入成功了,但是不支持RENAME操作。

接下来,从tbl表中读取数据。

之后,从第二会话尝试写入和读取数据:

MySQL将这些操作置于等待状态,你可以使用SHOW PROCESSLIST语句进行查看。

最后,释放第一次会话的锁定。

你将看到第二个会话中的所有操作执行成功。

LOCK TABLES对于VIEW加锁,LOCK TABLES语句会为VIEW中使用的所有基表加锁。对触发器使用LOCK TABLE,那么就会锁定触发器中所包含的全部表(any tables used in triggers are also locked implicitly)。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (2)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!