如何在MySQL 5.7中生成间隙锁定死锁

时间:2017-01-17 10:05:39

标签: mysql deadlock database-deadlocks mysql-5.7

我想在MySQL 5.7上显式生成间隙锁定死锁,以确保我的应用程序正确处理间隙锁定导致的死锁。我试图在网上遵循各种简单的例子,但是我不能解决僵局。我想生成MySQL检测到死锁并回滚其中一个事务(让另一个事务通过)的情况。

我测试这个的方式是我打开两个MySQL命令行窗口,在两个窗口中我都start transaction;,然后双方各自的查询尝试模拟它。

我尝试的几个例子是: http://thushw.blogspot.com.mt/2010/11/mysql-deadlocks-with-concurrent-inserts.html

并且:https://www.percona.com/blog/2012/03/27/innodbs-gap-locks/

5.7中的某些内容发生了变化,这使得它可以更好地检测间隙锁并避免它们。是否还有其他可以生成的简单示例?

1 个答案:

答案 0 :(得分:0)

这个问题可能已经过时。但是,我仍然想发布我的答案,以帮助其他有相同问题的人。

  1. 使用docker初始化Mysql 5.7环境:

docker compose 文件如下:

version: '3.3'
services:
  mysql:
    image: mysql:5.7
    container_name: lzy-test-db-mysql-57
    environment:
      MYSQL_ROOT_PASSWORD: xxxxx
      MYSQL_DATABASE: xxxxx
      MYSQL_USER: xxxxx
      MYSQL_PASSWORD: xxxxx
    ports:
      - 3307:3306

启动您的 mysql 5.7 docker

PS E:\docker-env\test\mysql\57> ls


    Directory: E:\docker-env\test\mysql\57


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        7/23/2020  10:26 AM            539 docker-compose.yml
PS E:\docker-env\test\mysql\57> docker-compose up -d
Creating network "57_default" with the default driver
Creating lzy-test-db-mysql-57 ... done
  1. 连接到您的mysql服务器。检查环境。 tx_isolation应该为RR
mysql> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
  1. 创建表格
CREATE TABLE `t` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `p_name` (`name`)
) ENGINE=InnoDB CHARSET=utf8;
  1. 准备数据
insert into t (name) value ('A'), ('C'), ('D');
  1. 生成间隙锁死锁
+====================================+============================================================+
|             Session A              |                         Session B                          |
+====================================+============================================================+
| begin;                             |                                                            |
+------------------------------------+------------------------------------------------------------+
|                                    | begin;                                                     |
+------------------------------------+------------------------------------------------------------+
| delete from t where name = 'C';    |                                                            |
+------------------------------------+------------------------------------------------------------+
|                                    | delete from t where name = 'C';  --Blocked!                |
+------------------------------------+------------------------------------------------------------+
| insert into t (name) values ('B'); |                                                            |
+------------------------------------+------------------------------------------------------------+
|                                    | ERROR 1213 (40001): Deadlock found when trying to get lock |
+------------------------------------+------------------------------------------------------------+

此死锁发生的原因,请参阅https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onbeforeunload