6

掉坑了!GROUP_CONCAT函数引发的线上问题

 3 years ago
source link: https://club.perfma.com/article/2367188
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
掉坑了!GROUP_CONCAT函数引发的线上问题 | PerfMa应用性能技术社区

掉坑了!GROUP_CONCAT函数引发的线上问题

阿飞云
GROUP_CONCAT
mysql
2天前

image.png
本文分享一篇在工作遇到的一个问题,关于MySQL GROUP_CONCAT函数导致的问题。希望能帮忙到你。

在说遇到的坑之前,先描述一下大致的业务场景。系统有一个排班的功能,一个医生一天可以排多种业务类型的排班,并且每一种业务类型的排班都支持排个多时段(时段的最小单位是15分钟)。

举例:
D医生在 2020-12-31 的 8:00~10:00、10:30~12:00  排班了【在线A】 和 【在线B】业务。

【在线A】 2020-12-31 8:00~10:00
【在线A】 2020-12-31 10:30~12:00
【在线B】 2020-12-31 8:00~10:00
【在线B】 2020-12-31 10:30~12:00

在查询这个一天排班的数据,伪SQL方便理解:

SELECT
 dt,
 biz_type,
 GROUP_CONCAT(
  CONCAT_WS('|', id, start_time, end_time)
 ) AS multiPeriodDetail
FROM
 doctor_schedule_detail
WHERE
 doctor_id = '456231'
AND dt = '2020-12-30'
GROUP BY
 doctor_id,
 biz_type,
 dt

CONCAT_WS(’|’, id, start_time, end_time)中的字段说明:

  • id:时段的id
  • start_time:时段开始时间
  • end_time:时段结束时间

对数据进行分组后,使用 CONCAT_WS函数 指定分隔符进行参数拼接。然后使用 GROUP_CONCAT 函数 返回分组中字符串结果组合连接的值,默认缺省为一个逗号 (",")进行分隔,这个缺省值可以去掉,本例子中使用默认缺省值。

查询后结果展示如下:
image.png
查询结果
至此场景描述结束。

这个代码在线上已经运行很长了,有一天用户反馈说给D医生排班了,但是界面查不到这个时段的排班数据。

经过"紧张激烈"的排查,终于找到了这个问题的罪魁祸首。

如上场景描述,在查询SQL中使用了 GROUP_CONCAT 函数,在业务中因为排班的最小时段为:单位是15分钟。正常医生不会拍很多很细的班,但在特殊的场景中,有一些医生就是15分钟排一次班,而且系统中真实的 CONCAT_WS函数拼接返回的字段比较多,那么导致查询出来的数据非常多, GROUP_CONCAT 函数就就大于默认值得数据丢弃了。

注:GROUP_CONCAT 对应的配置参数 group_concat_max_len 默认设置最大的长度 1024字节。

查询 group_concat_max_len 配置:

show variables like "group_concat_max_len";

tips:字段内容字节长度

MySQL utf-8 编码集, 一个中文占3个字节。

-- 字符长度 输出结果:6
SELECT CHAR_LENGTH("你好2021")
-- 字节长度 输出结果:10
SELECT LENGTH("你好2021")

在知道问题原因后,就有了对应的解决方案。
第一种方案:修改Mysql的配置,调整 group_concat_max_len 的值。

1 方法一:在MySQL的配置文件中加入如下配置(推荐):
2 
3 group_concat_max_len = 102400
4 方法二:更简单的操作方法,执行SQL语句:
5 
6 SET GLOBAL group_concat_max_len = 102400;
7  
8 SET SESSION group_concat_max_len = 102400;
9

生产环境,肯定要用方法一:在MySQL的配置文件。但考虑生产环境修改配置需要走一些流程和审批,于是有了第二种方案的考虑。

第二种方案:进行业务功能的调整,需求的调整或者GROUP_CONCAT 拼接少返回一些数据

功能已经上线,此时在修改,对业务有一定的影响
综合考虑后,决定更改group_concat_max_len的值,经过对业务的分析计算出具体要更改的值。

在真实场景中,大多数问题的解决方案不止一种,在权衡后找到一个符合当时的问题的最优解决方案。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK