mysql - MySQL 5.7中如何产生gap lock死锁

标签 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. Initial Mysql 5.7 environment by using docker:

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. Connect to your mysql server. Check environment. tx_isolation should be RR
mysql> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
  1. Create table
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. Prepare data
insert into t (name) value ('A'), ('C'), ('D');
  1. Generate gap lock deadlock
+====================================+============================================================+
|             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 |
+------------------------------------+------------------------------------------------------------+

出现这种死锁的原因,请引用How does MySQL (Innodb) perform next-key locking when deleting record

关于mysql - MySQL 5.7中如何产生gap lock死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41694169/

相关文章:

mysql - 如何在 mysql 连接查询中使用一列中的两个位置?

插入和更新中的 Postgresql 死锁

mysql - 如何使选择查询在具有 4 列(sno、sname、job、dept)、有 10 条记录的简单表上运行超过 30 分钟?

php - 将查询结果转换为 HTML 列表

MySQL远程: Alter privilege granted,但不工作

mysql - SQL继承性能

go - TCP `net.Conn.Read` 在使用 `encoding/gob` 解码器后挂起

c# - 事务(进程 ID)在锁定资源上与另一个进程发生死锁,并已被选为死锁牺牲品。重新运行交易

multithreading - 从异步方法访问记录器对象时死锁同步运行