一次诡异的数据库“死锁”,问题究竟在哪里?

简介: 程序死锁的问题,很难调试,看进程堆栈,看各个线程与锁的情况,对照代码进行排查。数据库死锁的问题,更难,看不了数据库堆栈,也看不了数据库线程与锁,更难以对照代码排查。

程序死锁的问题,很难调试,看进程堆栈,看各个线程与锁的情况,对照代码进行排查。

数据库死锁的问题,更难,看不了数据库堆栈,也看不了数据库线程与锁,更难以对照代码排查。

前段时间,和一个朋友讨论了一个“疑似”数据库死锁的问题,最后进行试验与排查,找到了问题所在。

场景如下:

image.png

同一个表,高并发事务,事务内先插入一条记录,再更新这条记录:

(1)如果更新的是唯一索引,有异常;

(2)如果更新的是自增主键,就没有异常;

画外音:先不要被“dead lock”描述所迷惑,是死锁问题,阻塞问题,还是其他异常,还另说。

image.png

而且,据朋友所述,还能够复现:

(1)开启事务;

(2)插入记录;

(3)sleep 5秒;

(4)修改被插入的记录;

在并发时稳定复现。

根据朋友的描述,在线下开了多个MySQL客户端进行了并发模式测试,结果还挺出乎意料的。

第一步:数据准备

create table t (

id int(20) primary key AUTO_INCREMENT,

cell varchar(20) unique

)engine=innodb;

新建表:

(1)存储引擎是innodb,MySQL版本是5.6;

(2)id字段,自增主键;

(3)cell字段,唯一索引;


start transaction;

insert into t(cell) values(11111111111);

insert into t(cell) values(22222222222);

insert into t(cell) values(33333333333);

commit;

插入一些测试数据。

第二步:session参数设置

事务的隔离级别,事务的自动提交等参数设置不当,都会对实验的结果产生影响,询问了朋友,事务的隔离级别是RR(repeatable read)。

set session autocommit=0;

set session transaction isolation level repeatable read;

每一个session启动后:

(1)关闭自动提交;

(2)把事务隔离级别设为RR;

image.png

show session variables like "autocommit";

show session variables like "tx_isolation";

不放心的话,可以用上面两个语句查询确认。

第三步:多个终端session模拟并发事务

image.png

如上图,用SecureCRT开启两个窗口:

(1)窗口A,先启动事务,并插入记录;

(2)窗口B,再启动事务,也插入记录;

(3)窗口A,修改插入的记录;

(4)窗口B,也修改插入的记录;

奇怪的现象发生了,如果并发事务的update语句:

(1)更新条件是cell,就会发生异常;

(2)更新条件是id,就一切正常;

按道理,插入不冲突的记录,然后修改这条记录,行锁不应该冲突呀?唯一索引,主键索引怎么会有差异呢?是否有关?是死锁,还是其他原因?

image.png

架构师之路-分享技术思路

目录
相关文章
|
SQL 存储 Oracle
数据库系列课程(20)-数据库死锁的原因及解决方案
数据库系列课程(20)-数据库死锁的原因及解决方案
318 0
|
11月前
|
算法 安全 数据库
数据库死锁的解决方案有哪些?
【10月更文挑战第28天】数据库死锁是数据库管理中的一个常见问题
500 71
|
SQL 关系型数据库 MySQL
遇到mysql数据库死锁,你会怎么排查?
遇到mysql数据库死锁,你会怎么排查?
896 0
|
11月前
|
数据库连接 数据库 数据库管理
如何避免数据库死锁?
【10月更文挑战第28天】
273 14
|
12月前
|
关系型数据库 MySQL 数据库
一个 MySQL 数据库死锁的案例和解决方案
本文介绍了一个 MySQL 数据库死锁的案例和解决方案。
717 3
|
12月前
|
SQL 数据库
达梦数据库阻塞死锁及解锁
【10月更文挑战第6天】本文介绍了在达梦数据库中模拟和解决死锁的方法。首先通过创建表并插入数据但不提交事务,模拟了阻塞情况;接着利用V$TRXWAIT和V$SESSIONS视图查询阻塞信息,并通过SP_CLOSE_SESSION函数解决阻塞。最后讨论了死锁的成因及避免策略,强调了正确管理事务的重要性。
|
Oracle 关系型数据库 MySQL
Mysql和Oracle数据库死锁查看以及解决
【8月更文挑战第11天】本文介绍了解决MySQL与Oracle数据库死锁的方法。MySQL可通过`SHOW ENGINE INNODB STATUS`查看死锁详情,并自动回滚一个事务解除死锁;也可手动KILL事务。Oracle则通过查询V$LOCK与V$SESSION视图定位死锁,并用`ALTER SYSTEM KILL SESSION`命令终止相关会话。预防措施包括遵循ACID原则、优化索引及拆分大型事务。
925 3
|
Oracle 关系型数据库 数据库
关系型数据库Oracle死锁
【7月更文挑战第16天】
238 3
|
SQL 存储 监控
达梦数据库死锁排查与解决
达梦数据库死锁排查与解决
2566 0
|
SQL 关系型数据库 MySQL
数据库的死锁原因及优化方案
数据库的死锁原因及优化方案
2966 16
数据库的死锁原因及优化方案

热门文章

最新文章