如何使 select 语句被阻止?

dav*_*jhp 5 mysql innodb deadlock select locking

您好,为了学习,我试图故意使 SQL select 语句被另一个简单的 SQL 删除或更新语句阻塞。我只喜欢 InnoDB 表。

为了准备测试,我创建了一个表

CREATE TABLE `test`.`client` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

并在表中插入了 1,000,000 行。


现在我要开始测试了。

在 MySQL 客户端 #1 中,我删除了所有行:

mysql #1> delete from client;
Run Code Online (Sandbox Code Playgroud)

当删除仍在执行时,在另一个 MySQL 客户端 #2 中,我尝试选择一行。

mysql #2> select * from client where id=1;
+---------+------+
| id      | name |
+---------+------+
| 1       | joe  |
+---------+------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

结果立即显示,选择没有被阻止。


接下来我将尝试另一个测试。我在表中插入了 1,000,000 行。

在 MySQL 客户端 #1 中,我更新了所有行:

mysql #1> update client set name='Bill';
Run Code Online (Sandbox Code Playgroud)

当更新仍在执行时,在另一个 MySQL 客户端 #2 中,我尝试选择一行。

mysql #2> select * from client where id=100;
+-----+------+
| id  | name |
+-----+------+
| 100 | joe  |
+-----+------+
1 row in set (0.00 sec)

mysql #2> select * from client where id=1000;
+------+------+
| id   | name |
+------+------+
| 1000 | joe  |
+------+------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

结果立即显示,选择没有被阻止。

所以现在我的问题是,如何使用 InnoDB 表演示 SQL 选择语句被另一个简单的 SQL 删除或更新语句阻塞?还是 MySQL 从来没有任何阻塞问题?

PS 我不是要模拟两个进程相互死锁,只是一个大的更新或插入阻止选择。

Rol*_*DBA 4

SELECT 造成的死锁可以通过多种方式实现。我写过关于他们的帖子

此级别类似于 REPEATABLE READ,但如果禁用自动提交,InnoDB 会隐式地将所有普通 SELECT 语句转换为 SELECT ... LOCK IN SHARE MODE。如果启用自动提交,则 SELECT 是其自己的事务。因此,它是只读的,如果作为一致(非锁定)读取执行,则可以序列化,并且不需要阻止其他事务。(如果其他事务已修改所选行,则要强制阻止普通 SELECT,请禁用自动提交。)

切入正题,你可以使用

  • SELECT ... FOR UPDATE,然后尝试SELECT针对这些行
  • SELECT ... LOCK IN SHARE MODE,然后尝试UPDATEDELETE这些行
  • 请参阅 MySQL 文档

试一试 !!!