1

我正在尝试在表格锁定的情况下测试一个场景。

我试图应用这样的读写锁 -

mysql> lock tables table_name write;
Query OK, 0 rows affected (0.01 sec)

但在此之后能够写 -

mysql> insert into table_name (id) values (1000000023);
Query OK, 1 row affected (0.00 sec)

读锁也不起作用。应用锁定后,我能够成功执行选择查询。

当我们对大量数据进行表迁移时,我需要测试我的应用程序行为(restful API),此时表上可能应用了写锁。所以,我想,如果我能够通过命令行设置锁,它也将适用于我的 API。我使用相同的用户登录命令行,就像我在应用程序中使用登录mysql一样。

如果我遗漏了什么,请告诉我。

该表是 InnoDb 类型的。

4

1 回答 1

1

我认为您误解了表锁定。根据文档

MySQL 允许客户端会话显式获取表锁,以便与其他会话协作以访问表,或者防止其他会话在会话需要独占访问表的期间修改表。会话只能为自己获取或释放锁。一个会话不能获取另一个会话的锁或释放另一个会话持有的锁。

您基本上锁定了其他会话,使其无法写入表,但您仍然可以在持有锁的同时对其进行写入。

对于您正在做的事情,该文档页面中有一个示例

将 LOCK TABLES 和 UNLOCK TABLES 与事务表(例如 InnoDB 表)一起使用的正确方法是使用 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;

当你调用 LOCK TABLES 时,InnoDB 内部会使用自己的表锁,而 MySQL 会使用自己的表锁。InnoDB 在下一次提交时释放它的内部表锁,但是要让 MySQL 释放它的表锁,你必须调用 UNLOCK TABLES。你不应该让 autocommit = 1,因为 InnoDB 在调用 LOCK TABLES 后立即释放它的内部表锁,死锁很容易发生。如果 autocommit = 1,InnoDB 根本不会获取内部表锁,以帮助旧应用程序避免不必要的死锁。

于 2019-08-12T14:39:01.233 回答