MySQL · 案例分析 · RDS MySQL线上实例insert慢常见原因分析

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: 概述insert慢是经常被问到的问题,笔者尝试在本文中对这个问题做一个分类梳理,列举的线上例子会做简化,希望对读者有所启发。注意:因为阿里云MySQL线上实例还是以RDS 5.6为主体,本文的分析也是以5.6 innodb 引擎为主,其他版本的rds的实例可能略有差别。

概述

insert慢是经常被问到的问题,笔者尝试在本文中对这个问题做一个分类梳理,列举的线上例子会做简化,希望对读者有所启发。 注意:因为阿里云MySQL线上实例还是以RDS 5.6为主体,本文的分析也是以5.6 innodb 引擎为主,其他版本的rds的实例可能略有差别。

insert几个可能的性能瓶颈点

有关MySQL insert源码分析的文章,可以参看阿里云云栖社区的文章,例如:

  1. 一条简单insert语句的调用栈
  2. 一条insert语句的执行过程

基于insert源码分析,和MySQL事务的一般过程,可以看出insert语句执行过程中几个可能的瓶颈点,包括加锁,io和网络几个方面,

  1. MDL锁, insert语句需要拿IX MDL 锁
  2. 外键检查对主表加S行锁
  3. insert转update操作需要的对老记录index entry的行锁
  4. iops限制
  5. 写binlog
  6. semi-sync消息延迟

下面我们来看几个实际的例子,每个例子都会尽量和读者一起来分享一下根因定位方法和问题规避建议,

insert语句慢示例分析

MDL锁等待

MDL锁等待阻塞DML语句的问题比较常见,一般都是因为表上有运行时间比较长的DDL语句在运行,比如Optimize, Truncate table,Alter table等,诊断方法也很简单, 通过运行show processlist,就会看到被阻塞的语句的状态是 Waiting for table metadata lock ,如果权限足够的话,还可以看到blocker thread, 规避的方法是避免在业务高峰运行DDL语句,特别是耗时很长的对大表的DDL。

外键检查等待对主表记录的S锁

如果是insert的目标表有定义外键依赖,MySQL需要做参照完整性(RI)检查,会对主表的对应记录加S锁。如果主表记录上正好有没有提交的修改,就会带来insert事务的锁等待。 在笔者写这篇文章的时候,RDS的慢日志项目里面的lock time字段并没有清晰的反映这种因为RI带来的锁等待时间消耗。 在问题出现的当场,运行下面的query查看I_S表,找出阻塞关系。这种方法有其局限性,只能抓现行,如果阻塞已经消除了,后期就看不到了。

SELECT
r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query,
(Unix_timestamp() - Unix_timestamp(r.trx_started)) blocked_time
from information_schema.innodb_lock_waits w
inner join information_schema.innodb_trx b
on b.trx_id = w.blocking_trx_id
inner join information_schema.innodb_trx r
on r.trx_id = w.requesting_trx_id

阿里云MySQL RDS有计划会改进慢SQL lock time的记录,记录外键检查对主表记录S锁的等待时间; 另外,还会将所有发生过阻塞的thread的信息记录在内存表里,供后期问题排查使用。

外键检查对主表记录加锁慢的规避方法是加速释放主表的X行锁,避免长事务;或者是通过业务而不是MySQL数据库来保证参照完整性。

insert转update操作需要拿老记录index entry上的S/X锁

如果新插入的记录项已经存在,但已经被标记为已删除,或者是使用了INSERT ON DUPLICATE KEY UPDATE, MySQL会将insert操作转成update操作。就会对老的index 项目加上X锁(如果是cluster index对应的记录则加S锁),来确保原有记录的删除/修改事务已经提交。

------------------------
LATEST DETECTED DEADLOCK
------------------------
...
*** (1) TRANSACTION:
TRANSACTION 82234303407, ACTIVE 0.000 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 1
LOCK BLOCKING MySQL thread id: 1275826132 block 1242176372
MySQL thread id 1242176372, OS thread handle 0x2abbbf103700, query id 30359943998 ...  push_service update
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12214 page no 672677 n bits 264 index ... of table ... trx id 82234303407 lock_mode X waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
...

*** (2) TRANSACTION:
TRANSACTION 82234303405, ACTIVE 0.001 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1184, 3 row lock(s), undo log entries 1
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 12214 page no 672677 n bits 264 index `...` of table ... trrx id 82234303405 lock_mode X
Record lock, heap no 10 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
...

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12214 page no 672677 n bits 264 index `...` of table ...  trx id 82234303405 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
...

*** WE ROLL BACK TRANSACTION (1)

上面是多条INSERT ON DUPLICATE KEY UPDATE并发执行导致的死锁,在master error log里面可以观测到。

这种问题的诊断可以通过查看慢日志的lock time字段来判断;如果发生了死锁,还可以查看master error log,也可类似MDL锁等待,从I_S表查看当前的阻塞关系。

iops限制

笔者曾经遇到过insert作业时不时会变慢,但前端业务并没有什么高峰尖刺。后台分析可以看到用户binlog使用很重,大概每2分钟就会产生将近600M的binglog文件,依赖rds的系统诊断工具上也能观察到iops 打满的问题。

iops full.png

因为慢insert有明显的时间规律,怀疑有定期批处理。和客户沟通后,确认客户有设置event scheduler,每分钟会进行全表的数据归集操作,io压力比较大。后期让客户调整他们的数据归集逻辑后,insert慢的问题消失。

写binlog延迟

笔者还遇到一条insert语句一直没有成功返回, show processlist显示该条insert语句的状态是query end。笔者打印了当时的pstack信息,发现了如下的调用栈

#0  0x0000003c00eab91d in nanosleep () from /lib64/libc.so.6
#1  0x0000003c00eab790 in sleep () from /lib64/libc.so.6
#2  0x00000000009967c6 in wait_for_free_space ()
#3  0x00000000009b29d9 in my_write ()
#4  0x000000000099a547 in my_b_flush_io_cache ()
#5  0x0000000000958892 in MYSQL_BIN_LOG::ordered_commit(THD*, bool, bool) ()
#6  0x0000000000959214 in MYSQL_BIN_LOG::commit(THD*, bool) ()
#7  0x000000000062c870 in ha_commit_trans(THD*, bool, bool) ()
#8  0x00000000008200e9 in trans_commit_stmt(THD*) ()
#9  0x000000000078aba1 in mysql_execute_command(THD*) ()
#10 0x00000000007910b0 in mysql_parse(THD*, char*, unsigned int, Parser_state*) ()
#11 0x0000000000792805 in dispatch_command(enum_server_command, THD*, char*, unsigned int) ()
#12 0x0000000000754535 in do_handle_one_connection(THD*) ()
#13 0x0000000000754589 in handle_one_connection ()
#14 0x0000003c01207851 in start_thread () from /lib64/libpthread.so.0
#15 0x0000003c00ee767d in clone () from /lib64/libc.so.6

这个调用栈很明显的说明了问题所在,就是binlog的磁盘没有剩余空间了,导致insert hang住。清理出足够的磁盘空间后,insert执行结束。

需要指出的是,MySQL 8.0增加了新的thread stage WAITING FOR DISK来提示等待磁盘空间,来辅助诊断,对应的commit id是’6de594adf488add4514884d18c337745b1d227fb’。

semi-sync消息延迟

在有主备复制环境下,semi-sync消息延迟也可能导致insert变慢。笔者遇到一个慢insert,杜康慢日志显示此insert的执行时间正好是1秒。

查看master error log,发现在insert出现的时间点正好有这种信息

...[Warning] Timeout waiting for reply of binlog (file: mysql-bin.000903, pos: 2519326), semi-sync up to file mysql-bin.000903, position 2519003.

而系统参数rpl_semi_sync_master_timeout也正好是1秒。因此,可以判定是因为网络抖动,semi-sync消息延迟导致的insert变慢。

总结

mysql insert语句执行慢的可能原因比较多,涵盖cpu,io,网络,锁等,在本文中分析了MySQL实例负载大,唯一键update、外键检查加锁带来的锁等待,semi-sync的网络开销,磁盘io限制,binlog日志满等导致的insert慢的问题。具体的原因需要具体分析,分析方法包括查看mysql已有的master-error log, slow log,另外,阿里云rds提供了强大的图形化工具包括我们查看系统负载曲线,慢日志详情,系统卡慢归总信息等,rds mysql内核团队有对定制系统诊断的能力,例如为慢日志添加更细的指标信息,包括锁等待时间等,并且也在一直加强对诊断问题缺失信息的补全,这些信息对于我们分析各种MySQL的性能问题都有很大的辅助。另外,保持MySQL版本的及时更新也是减少慢query或者是加快慢query诊断的推荐做法。

相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
7月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
7月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1157 152
|
7月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
890 156
|
8月前
|
存储 SQL 关系型数据库
RDS DuckDB技术解析一:当 MySQL遇见列式存储引擎
RDS MySQL DuckDB分析实例以​列式存储与向量化计算​为核心,实现​复杂分析查询性能百倍跃升​,为企业在海量数据规模场景下提供​实时分析能力​,加速企业数据驱动型决策效能。​​
|
7月前
|
存储 弹性计算 关系型数据库
如何通过控制台创建RDS MySQL实例
本文介绍了通过控制台创建RDS MySQL实例的详细步骤,包括准备工作、选择计费方式、地域、实例规格、存储空间等关键配置,并指导用户完成下单与实例查看。
|
8月前
|
存储 关系型数据库 MySQL
【赵渝强老师】MySQL数据库的多实例环境
MySQL多实例是指在一台服务器上运行多个MySQL服务,通过不同端口提供独立的数据服务。各实例共享安装程序,但使用各自的配置文件和数据文件,实现资源高效利用。本文详细介绍了如何通过“mysqld_multi”工具配置和启动多个MySQL实例,并演示了目录创建、初始化、配置文件修改及实例启动等操作步骤。
342 1
|
7月前
|
关系型数据库 MySQL 数据库
云时代MySQL:RDS与自建数据库的抉择
在云计算时代,选择合适的数据库部署方案至关重要。本文深入对比了AWS RDS与自建MySQL的优劣,帮助您在控制权、运维成本和业务敏捷性之间找到最佳平衡点。内容涵盖核心概念、功能特性、成本模型、安全性、性能优化、高可用方案及迁移策略,为您提供全面的决策参考。
|
8月前
|
关系型数据库 MySQL 程序员
从自建MySQL到阿里云RDS:程序员的数据库减负革命
如果你正在为自建MySQL数据库的高成本运维发愁,为凌晨三点的主从同步故障告警而崩溃,为开发团队频繁索要新测试库的要求感到窒息——是时候开启一场数据库的自我救赎了。 程序员更需构建"技术敏锐度+工程落地能力+跨域协作"的三维竞争力,通过创建技术组合形成差异化优势。企业应建立持续学习机制,提供AI沙盒环境促进技术转化。
|
11月前
|
前端开发 关系型数据库 RDS
购买RDS实例报错SLR 授权:未授权,应该怎么处理?
在阿里云购买RDS实例时,可能会遇到“SLR未授权”的报错。解决方法如下:1. 使用主账号登录控制台以确保权限充足;2. 在RDS购买页面选择正确的地域、引擎和产品系列,触发授权弹窗;3. 确认授权即可解决问题,若出现前端Bug导致报错,刷新页面即可。建议优先使用主账号避免RAM子账号权限配置复杂的问题。
481 29
|
11月前
|
存储 关系型数据库 MySQL
【免费动手教程上线】阿里云RDS MySQL推出大容量高性能存储:高性能本地盘(最高16TB存储空间)、高性能云盘(最高64TB存储空间)
阿里云RDS MySQL提供高性能本地盘与高性能云盘等存储方案,满足用户大容量、低延迟需求。高性能本地盘单盘最大16TB,IO延时微秒级;高性能云盘兼容ESSD特性,支持IO性能突发、BPE及16K原子写等能力。此外,阿里云还提供免费动手体验教程,帮助用户直观感受云数据库 RDS 存储性能表现。

相关产品

  • 云数据库 RDS MySQL 版
  • 云数据库 RDS
  • 推荐镜像

    更多