一次诡异的线上数据库的死锁问题排查过程

本文记录了一次线上数据库死锁问题的排查过程,涉及MySQL的InnoDB锁机制、隔离级别和索引。通过死锁日志分析,发现死锁源于非主键索引的前缀相同导致的加锁顺序不同。解决方案包括调整索引前缀长度或修改代码,避免多条更新语句在同一事务中修改同一条记录。
摘要由CSDN通过智能技术生成

前几天,线上发生了一次数据库死锁问题,这一问题前前后后排查了比较久的时间,这个过程中自己也对数据库的锁机制有了更深的理解。本文总结了这次死锁排查的全过程,并分析了导致死锁的原因及解决方案。希望给大家提供一个死锁的排查及解决思路。

本文涉及到MySql执行引擎、数据库隔离级别、Innodb锁机制、索引、数据库事务等多领域知识。前车之鉴,后事之师,希望读者们都可以有所收获。

 

1

现象

某天晚上,同事正在发布,突然线上大量报警,很多是关于数据库死锁的,报警提示信息如下:

 

{"errorCode":"SYSTEM_ERROR","errorMsg":"nested exception is org.apache.ibatis.exceptions.PersistenceException: 
Error updating database. Cause: ERR-CODE: [TDDL-4614][ERR_EXECUTE_ON_MYSQL] 
Deadlock found when trying to get lock; 
The error occurred while setting parametersn### SQL: 
update fund_transfer_stream set gmt_modified=now(),state = ? where fund_transfer_order_no = ? and seller_id = ? and state = 'NEW'

通过报警,我们基本可以定位到发生死锁的数据库以及数据库表。先来介绍下本文案例中涉及到的数据库相关信息。

 

2

背景情况

我们使用的数据库是Mysql 5.7,引擎是InnoDB,事务隔离级别是READ-COMMITED。

数据库版本查询方法:

 

select version();

引擎查询方法:

 

show create table fund_transfer_stream;

建表语句中会显示存储引擎信息,形如:ENGINE=InnoDB

事务隔离级别查询方法:

 

select @@tx_isolation;

事务隔离级别设置方法(只对当前Session生效):

 

set session transaction isolation level read committed;

PS:注意,如果数据库是分库的,以上几条SQL语句需要在单库上执行,不要在逻辑库执行。

发生死锁的表结构及索引情况(隐去了部分无关字段和索引):

 

CREATE TABLE `fund_transfer_stream` ( 
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间', 
  `pay_scene_name` varchar(256) NOT NULL COMMENT '支付场景名称', 
  `pay_scene_version` varchar(256) DEFAULT NULL COMMENT '支付场景版本',
  `identifier` varchar(256) NOT NULL COMMENT '唯一性标识',
  `seller_id` varchar(64) NOT NULL COMMENT '卖家Id',
  `state` varchar(64) DEFAULT NULL COMMENT '状态', `fund_transfer_order_no` varchar(256) 
  DEFAULT NULL COMMENT '资金平台返回的状态', 
  PRIMARY KEY (`id`),UNIQUE KEY `uk_scene_identifier` 
  (KEY `idx_seller` (`seller_id`),
  KEY `idx_seller_transNo` (`seller_id`,`fund_transfer_order_no`(20))
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资金流水';

该数据库共有三个索引,1个聚簇索引(主键索引),2个非聚簇索(非主键索引)引。

聚簇索引:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值