问题现象

日志库大量进程阻塞,导致服务不可用。

日志库状况描述

数据特点

数据库是用于存储用户点击、激活、登录、付费等所有日志,使用了 Tokudb 存储引擎。特别是点击数据,现在已经达到 2亿 量级。

进程状态

当时登录到数据库中查询到有很多进程处于 Sending data 和 open table 状态,数据库处于极度阻塞的状态。

Sending data 和 open table 状态的进程是来自 select 语句,加上其他 insert 语句带来的进程,数据库实时的进程数在百级别了(这里稍微记一下,后面分析open table会用到)。

机器状态

主要关注 00:00~00:57左右,这个时间cpu是处于一个十分繁忙的状态。因为此时数据库在进行大量的回表读操作(下面会分析到)。
00:57分后人工干预了,机器就瞬间恢复到正常水平。

但此时内存使用却是一天中的较低水平,这里没想清楚、

业务描述

上面处于 Sending data 和 open table 状态的进程都是来自同一个业务的查询。
eg:

select adv_position_id, id, pf, click_time, device_id, ua, channel, common_field from click_log where click_date >= '20210220' and pf = 1 and game_id = 200004426 and device_id in ('ffffffff-dcf1-4d3e-6036-c5de1c00c39e', '8fd962d037e694364092aee24c7cfd62', '8FD962D037E694364092AEE24C7CFD62', '', 'd41d8cd98f00b204e9800998ecf8427e', 'D41D8CD98F00B204E9800998ECF8427E', '863709034406035', 'acfeccc2df75e20f90be256cd33fa94e', 'ACFECCC2DF75E20F90BE256CD33FA94E');

这条语句会根据imei、oaid、device_id等多个纬度的不同的变形去找到对应的点击。原本是很简单的查询,但是耐不住量大。

以上述单体语句来说:符合这条查询的记录在20万左右。数据库同时有上百数据类似的语句同时查询。

这里插个题外话,这些点击基本上来自媒体:快手。这个倒不奇怪,快手这个媒体经常发很多很多的点击过来,一直怀疑这厮就是在撞归因。极度反感!

Sending data

在解析为什么很多进程卡在 Sending data 处先解释下 Sending data 是啥。这种状态的经常通常是来自 select 语句,一个简单的 select 会经历的阶段大致是如下:

 THD::enter_stage: 'checking permissions' THD::enter_stage: 'Opening tables' THD::enter_stage: 'init' THD::enter_stage: 'System lock' THD::enter_stage: 'optimizing' THD::enter_stage: 'statistics' THD::enter_stage: 'preparing'THD::enter_stage: 'executing'THD::enter_stage: 'Sending data' THD::enter_stage: 'end' THD::enter_stage: 'query end' THD::enter_stage: 'closing tables' THD::enter_stage: 'freeing items'

Sending data 阶段数据库并不是单纯的发送数据,而是包括“收集 + 发送”过程。
发送是引擎把数据同步给数据库客户端,而收集则受查询使用索引区别有很大的影响。

  1. 不需要回表。如根据主键索引、联合索引(索引覆盖)查询,需要的数据就在索引树中。
  2. 需要回表。 上面的查询的语句不幸就是需要回表的。

回表就算了,查询中还有个字段(common_field)有点特殊,它是 varchar(1024)。

数据库有个操作是存储较长的字段时候,只会存储前768字节的长度,剩余的数据存放到“溢出页”中。这不就更雪上加霜!一旦采用了这种方式存储,返回数据的时候本来是顺序读取的数据,就变成了随机读取了,所以导致性能急剧下降。

我这边测试上述举例的语言原本需要十几秒,去掉common_field后,节省了几秒。

数据条数多、列数据长度加起来,就让单条查询需要花费十几秒以上。然后这些查询是3分钟一次的频率不停的查询,导致大量的进行处于 sending data 状态。

然后这并不是最糟的,不停的堆积引发了另一种状态 Opening tables 的产生。

Opening tables

当 open_tables 值大于 table_open_cache 值时,每次新的 session 打开表,有一些无法命中 table cache,而不得不重新打开表。这样反应出来的现象就是有大量的线程处于 opening tables 状态。

这个数据库总的在使用的表就7张,所以引发这种情况的原因就是大量的 Sending data 进程。

Opened_tables状态变量,该变量指示自服务器启动以来表打开操作的数量。
使用 SHOW GLOBAL STATUS LIKE ‘Opened_tables’;

+---------------+-------+
| Variable_name | Value
+---------------+-------
| Opened_tables | 38466 |
+---------------+-------+

而数据库设置的 table_open_cache 值是1024。为啥打开表数量那么多昵?

官方文档有着这样的解释:table_open_cache is related to max_connections. For example, for 200 concurrent running connections, specify a table cache size of at least 200 * N, where N is the maximum number of tables per join in any of the queries which you execute.

数据库使用的版本是 10.0.13-MariaDB,故直接看对应的 MySQL 5.6的文档即可。
N 代表所执行的任何查询中每个连接的最大表数。我这边虽然都是单表查询,但是数量取胜(session太多)。

故有着大量的 opening tables 状态进行的产生。

官方的建议是:If the value is very large or increases rapidly, even when you have not issued many FLUSH TABLES statements, increase the table_open_cache value at server startup.

但我没这么做,我清楚这一切的产生都是 sql 的问题导致的。

总结

当时看到两种状态的大量进程存在,我原本是按照查询的阶段顺序看,所以先从 Opening tables 入手,然后发现不对。所以转头从 sending data 入手,最后基于对业务、机器的了解,完成了这次问题的排查。

MySQL - 大量 sending data 状态进程,让数据库性能急剧下降。相关推荐

  1. mysql堵塞 sending data和sort状态多,cpu高

    访问MySQL频繁超时,隔一阵子就堵塞一会儿. 用show processlist 看看正在执行的语句.表现如下: 1.有100多个语句在执行,查询语句集中在两个表A和B,大多数都是select语句, ...

  2. mysql sending data状态

    select * from searchzh where modified_date > '2009-09-02 14:45:22'; 一条mysql查询语句的性能:sending data 耗 ...

  3. mysql查询Sending data慢耗时长

    问题场景: 在一个数据量为70W+的表中使用count计数查询,因为有使用到like模糊查询,导致索引无效,查询时间增至30秒 分析: 经分析在查询中Sending data耗时很大,占60%以上的时 ...

  4. MySQL磁盘io瓶颈原因_为什么当磁盘IO成瓶颈之后数据库的性能急剧下降

    展开全部 为什么当磁盘IO成瓶颈之后, 数据库的性能不是达到饱和e68a84e8a2ad3231313335323631343130323136353331333433643733的平衡状态,而是急剧 ...

  5. mysql io瓶颈,(续)为什么当磁盘IO成瓶颈之后数据库的性能急剧下降—性能更悲剧篇...

    我们来梳理一下数据页访问的流程: 1. 先看缓存池中有没有,如果没有,则需要访问磁盘. 2. 访问磁盘之前,是不是需要先提前准备好一个空闲的内存块来接收(存放)磁盘上的数据页的内容? 很显然,这个空闲 ...

  6. 拜托,别再问我数据库性能优化了!

    一.前言 在谈论数据库的时候,经常能够听到"QPS"."TPS"等词汇,其实吞吐量不过是数据库性能的呈现,对于数据库性能的本质,我更倾向于将其描述为响应时间量, ...

  7. MySQL Sending data导致查询很慢的问题详细分析

    这两天帮忙定位一个MySQL查询很慢的问题,定位过程综合各种方法.理论.工具,很有代表性,分享给大家作为新年礼物:) [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的 ...

  8. sending data mysql_MySQL查询中Sending data占用大量时间的问题处理

    原SQL执行计划: EXPLAIN SELECT tm.id, tm.to_no , tm.source_website_id , tm.warehouse_name , tm.target_webs ...

  9. 数据库性能优化—MySQL单表最大记录数超过多少时性能会严重下降

    以前没有想过MySQL数据库的单表最大行数,直到最近interview时被问到c语言中int类型的最大值是多少时才想到Mysql单表最大行数的问题. 一开始被问到C语言中int类型的最大值有点懵逼,一 ...

  10. Oracle优化01-引起数据库性能问题的因素

    思维导图 概述 一个数据库是否存在性能问题,基本上在系统设计的时候就决定了,这个系统设计包括软件的设计.数据库的设计和硬件的设计.其中更细节的分类参考目录. 在一个系统的设计阶段,其中任何一个环节存在 ...

最新文章

  1. Python学习—函数
  2. u-boot移植第四弹——2013.10u-boot增加dm9000的支持
  3. data-sap-ui-icon-content where does icon content come from
  4. Java将五个整数存入整形数组_异常处理:从命令行输入5个整数,放入一整型数组,然后打印输出。。。...
  5. java单词测试,java单词 - 在线打字测试(dazi.kukuw.com)
  6. 【C++基础学习】二维数组的动态分配及参数传递
  7. 蓝桥杯 ALGO-105 算法训练 黑色星期五
  8. Java求解自由落体相关问题
  9. [游戏制作]-C语言实现井字棋(三子棋)游戏简单版
  10. 结对第一次—原型设计
  11. 【您还有心跳吗?超时机制分析 】
  12. ArcGIS 如何卸载再重装
  13. 校园网自动登录(校园翼行网)
  14. Android反编译工具
  15. 光敏传感器实验报告_光敏电阻传感器实验报告
  16. 算法竞赛入门【码蹄集新手村600题】(MT1101-1150)
  17. APS计划排程系统和生产排产系统,需要哪些基础资料(一)
  18. 新手常见(五国)(-v图)错误解决(原版,破解kernel,补丁kext下载)
  19. 小鸡腿U T6 2013FINAL
  20. 开源数据库全接触-MongoDB,Cassandra,Hypertable,CouchDB,Redis,HBase,Voldemort等35款数据库简介

热门文章

  1. IDEA启动My Eclipse项目
  2. 各种快递API接口—爱快递
  3. zmq pub/sub使用详解
  4. WINDOWS API编程乱叹
  5. ADXL345调试心得
  6. 一次因JDK夏令时导致接口输出日期格式的时间与预期时间不一致的bug排查
  7. 免费不限流的内网穿透,外网共享内网文件
  8. For ‘mall-coupon‘ URL not provided. Will try picking an instance via load-balancing. org.springfram
  9. 操作系统引导程序顺序
  10. 内外网隔离--网络准入控制系统有什么功能