【巡检问题分析与最佳实践】PolarDB 死锁问题

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 死锁是关系型数据库系统中最为常见的错误,出现在不同事务中同时对某些数据访问加锁时都要等待对方请求中的数据而无法获取锁,数据库系统会自动牺牲回滚代价最小的事务,从而导致对应的写请求失败,更严重的情况是在大量死锁发生时,会导致数据库系统效率低下,堆积进程大量堆积引发性能问题。
+关注继续查看

往期分享

RDS MySQL

RDS MySQL 实例空间问题

RDS MySQL 内存使用问题

RDS MySQL 活跃线程数高问题

RDS MySQL 慢SQL问题

RDS MySQL 实例IO高问题

RDS MySQL 小版本升级最佳实践

RDS PostgreSQL

RDS PostgreSQL 实例IO高问题

RDS PostgreSQL 慢SQL问题

RDS PostgreSQL CPU高问题

RDS SQL Server

RDS SQL Server 磁盘IO吞吐高问题

RDS SQL Server CPU高问题

RDS SQL Server 空间使用问题

PolarDB

PolarDB MySQL CPU高问题

PolarDB 流量 & 代理问题

Redis

Redis 流控问题

Redis 内存高问题

Redis CPU高问题

MongoDB

MongoDB 内存高问题

MongoDB 磁盘IO高问题

MongoDB 空间使用问题

背景

死锁是关系型数据库系统中最为常见的错误,出现在不同事务中同时对某些数据访问加锁时都要等待对方请求中的数据而无法获取锁,数据库系统会自动牺牲回滚代价最小的事务,从而导致对应的写请求失败,更严重的情况是在大量死锁发生时,会导致数据库系统效率低下,堆积进程大量堆积引发性能问题。

一般来说,死锁都是由于逻辑加锁的顺序导致的,也就是我们常说的 ABA死锁,举例:

image

tran_A 与 tran_B两个请求分别持有对方所需要的第二次update的行锁,就形成了死锁:

image


此时业务会收到报错信息类似:

Error : Deadlock found when trying to get lock; try restarting transaction

观察数据库内信息:

show engine innodb status\G;
------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-12-01 16:43:28 0x7fe8a0277700
*** (1) TRANSACTION:
TRANSACTION 370942954, ACTIVE 9 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 25713, OS thread handle 140637097146112, query id 237499 106.11.34.226 luhuo_h updating
update sbtest1 set c='tran2_tran1' where id=1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 354 page no 4 n bits 144 index PRIMARY of table `sbtest`.`sbtest1` trx id 370942954 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000161c23e9; asc     # ;;
 2: len 7; hex 23000000151374; asc #     t;;
 3: len 4; hex 80c52f66; asc   /f;;
 4: len 30; hex 7472616e3120202020202020202020202020202020202020202020202020; asc tran1                         ; (total 120 bytes);
 5: len 30; hex 32323139353230373034382d37303131363035323132332d373431343033; asc 22195207048-70116052123-741403; (total 60 bytes);
*** (2) TRANSACTION:
TRANSACTION 370942953, ACTIVE 15 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 25568, OS thread handle 140637096081152, query id 237597 106.11.34.226 luhuo_h updating
update sbtest1 set c='tran1_tran2' where id=2
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 354 page no 4 n bits 144 index PRIMARY of table `sbtest`.`sbtest1` trx id 370942953 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000161c23e9; asc     # ;;
 2: len 7; hex 23000000151374; asc #     t;;
 3: len 4; hex 80c52f66; asc   /f;;
 4: len 30; hex 7472616e3120202020202020202020202020202020202020202020202020; asc tran1                         ; (total 120 bytes);
 5: len 30; hex 32323139353230373034382d37303131363035323132332d373431343033; asc 22195207048-70116052123-741403; (total 60 bytes);
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 354 page no 4 n bits 144 index PRIMARY of table `sbtest`.`sbtest1` trx id 370942953 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; hex 80000002; asc     ;;
 1: len 6; hex 0000161c23ea; asc     # ;;
 2: len 7; hex 24000000191844; asc $     D;;
 3: len 4; hex 8021f170; asc  ! p;;
 4: len 30; hex 7472616e3220202020202020202020202020202020202020202020202020; asc tran2                         ; (total 120 bytes);
 5: len 30; hex 32383733333830323932332d31303534383839343634312d313138363735; asc 28733802923-10548894641-118675; (total 60 bytes);
*** WE ROLL BACK TRANSACTION (2)

但是引擎层打印出的太过于晦涩,难以定位问题,本文主要描述以云上已有工具进行业务逻辑的定位方法

另外,本文说的死锁是指deadlock,而非事务锁造成的阻塞(block),要区分排查。

定位

基础分析

通过实例控制台->一键诊断->锁分析入口进入,选择立即诊断,如果实例存在死锁,会在【发现死锁】列出现 【是】。

需要说明的是,目前诊断功能只能拉取最后一次死锁,同样是从innodb status中获取的,如果实例不重启,死锁信息会一直保留最后一组日志,所以需要确认诊断后的日志是不是存量死锁问题,也就是说发现死锁不一定是新出现的死锁。

目前DMS平台正在排期全量死锁记录的功能,到时会有真实的全量死锁信息。

image

发现死锁后,点击查询详情页,会显示格式化后的死锁信息:

image


  • Thread id : 线程ID,和洞察中的线程ID对应
  • 涉及表:死锁出现的表,有时可能左右表不一致,是因为事务中请求的表不致的问题
  • 等待锁索引名: DML语句会将锁加在索引行上,所以获取不到的锁一定是在某个索引上
  • 事务SQL : 引发死锁的语句


以上信息是一个简单死锁的基本情况,但是由于MySQL的死锁信息相对简单,如果是一组事务中的几个语句导致加锁顺序不对,在死锁信息中无法定位,如果是简单业务,可以将【事务SQL】给到研发人员进行语句级别的定位,但是由于有些业务逻辑过于复杂,开发也无法确认事务流,此时就需要进一步将整个事务进行定位。


事务流定位

事务流定位的前提条件是在死锁发生前,开启了sql洞察功能,才能对执行过的语句进行定位。

首先可以获取的信息是:

    1. 回滚的事务
    2. 发生死锁的语句
    3. thread_id 


  • 错误线程定位

牺牲事务thread_id 为 1622,成功thread id 为1746,先对牺牲事务进行定位:

image


状态中显示 【失败(1213)】,error 1213就是死锁回滚的code,所以可以定位发生回滚的事务:

image

默认返回是秒级排序,如果要获取时序的事务流,需要通过 【执行时间(毫秒)】进行排序,注意如果返回语句太多,将无法进行【执行时间(毫秒)】排序,需要继续缩小时间短,减小返回审计数据。

同时知道执行成功的thread id 为1746 ,可以再次进行定位:

image

分析日志可获取事务时间线:

image


至此死锁链的事务流已经分析出来,可以交由业务人员进行代码定位了。


注意事项

  • 在查找SQL审计内容时,有可能出现大量的语句导致无法分析,需要不断的缩短时间范围以定位准确区间
  • 需要明确出现的报错语句为error 1213错误才是死锁退出的语句
  • 如果业务无没有开启事务,有可能是在框架中配置的,一般开始语句都是set autocommit=0,有begin开始事务的情况不是很多。
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
2月前
|
存储 监控 关系型数据库
PolarDB 常用情景
PolarDB 常用情景
102 0
|
9月前
|
SQL 运维 监控
OceanBase 4.0 解读:全链路追踪要解决什么问题?从一条慢SQL说起
曾多次参加蚂蚁双十一大促支持工作,是TPC-C、TPC-H性能攻坚项目组核心成员,主要负责SQL引擎相关研发,包括链路协议、执行计划管理、执行引擎等方向的设计与开发工作。
226 0
OceanBase 4.0 解读:全链路追踪要解决什么问题?从一条慢SQL说起
|
SQL 存储 容灾
24PostgreSQL 日常维护和巡检 | 学习笔记(二)
快速学习24PostgreSQL 日常维护和巡检
693 0
24PostgreSQL 日常维护和巡检 | 学习笔记(二)
|
SQL 存储 Java
24PostgreSQL 日常维护和巡检 | 学习笔记(一)
快速学习24PostgreSQL 日常维护和巡检
509 0
24PostgreSQL 日常维护和巡检 | 学习笔记(一)
|
监控 关系型数据库 OLAP
AnalyticDB PostgreSQL监控告警诊断练习题
AnalyticDB PostgreSQL监控告警诊断练习题
130 0
|
关系型数据库 OLAP PostgreSQL
AnalyticDB PostgreSQL故障修复练习题
AnalyticDB PostgreSQL故障修复练习题
113 0
|
SQL NoSQL 关系型数据库
【巡检问题分析与最佳实践】PolarDB 流量 & 代理问题
PolarDB集群原生支持读写分离方式接入业务,但是在真实业务中,经常出现节点上负载不均情况,严重的话可能导致单节点承担大量的流量被拖跨,最终整个集群雪崩影响业务。本文主要描述PolarDB代理的配置方法以及流量不均时如何定位。
【巡检问题分析与最佳实践】PolarDB 流量 & 代理问题
|
SQL 缓存 NoSQL
【巡检问题分析与最佳实践】PolarDB MySQL CPU高问题
CPU做为数据库资源最核心的资源,是日常最重点需要关注的指标,CPU用满,会导致应用RT增高、业务卡顿,更严重会导致数据库实例hang死发生ha等问题,严重影响日常生产业务。 一般对于CPU的监控需要设定安全水位,超出安全水位要及时处理,否则会引发不可预期的严重后果。
【巡检问题分析与最佳实践】PolarDB MySQL CPU高问题
|
SQL 弹性计算 关系型数据库
PolarDB如何应对大并发复杂查询最佳实践
MySQL架构是单线程处理SQL,遇到大并发复杂查询时,需要排队长时间等待,容易形成慢查询,影响业务。PolarDB并发查询能力可以很好解决此问题。
PolarDB如何应对大并发复杂查询最佳实践
|
SQL 监控 NoSQL
【巡检问题分析与最佳实践】MongoDB 内存高问题
本文将由浅入深帮您查看、分析和优化云数据库MongoDB的内存使用。
【巡检问题分析与最佳实践】MongoDB 内存高问题
相关产品
云数据库 RDS MySQL 版
云原生数据库 PolarDB
推荐文章
更多