MySQL的GROUP_CONCAT函数,在做分组字符串拼接时几乎是标配。无论是统计用户的订单号、拼接文章的标签,还是汇总部门的所有员工姓名,只要是多行转一行的场景,基本都离不开它。
但问题是——超过90%的开发者都踩过一个很隐蔽的坑。今天又有同事来跟我沟通这个问题,实在觉得有必要拎出来好好讲清楚。
正常用着的时候,一切表现都很完美。可一旦拼接的数据量稍微大一点,结果就悄无声息地消失了——不是报错,不是警告,就是直接给你一个不完整的数据。线上业务莫名其妙开始异常,数据对不上,定位起来让人毫无头绪。
这个问题的根源,其实就出在GROUP_CONCAT背后的一个核心参数:group_concat_max_len,它的默认值,实在是太短了。
下面就从最容易触发的截断问题入手,一步步带你精准复现问题、搞懂原理,最后彻底解决。
一、异常复现
在默认配置下,GROUP_CONCAT的截断几乎是必然触发的。MySQL把group_concat_max_len默认设成了1024字节——拼接结果一旦超过这个长度,数据直接被截断,没有任何提示。
1. 测试数据准备
先建一张测试表,导入一批总长度超过1024字节的数据,复现起来才会足够直观。
-- 1. 创建测试表
CREATE TABLE `test_data` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`group_id` INT,
`content` VARCHAR(50)
);
-- 2. 批量插入大量数据(总长度远超1024字节,必触发截断)
INSERT INTO `test_data` (group_id, content)
SELECT 1, CONCAT('item_', FLOOR(RAND()*10000))
FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) t1,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) t2,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) t3;

2. 复现截断场景
我的测试环境之前已经调过参数,所以这次需要先还原一下会话级参数,才能复现那个经典的截断效果。

先把参数改回默认值:
mysql> SET SESSION group_concat_max_len = 1024;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'group_concat_max_len';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| group_concat_max_len | 1024 |
+----------------------+-------+
1 row in set (0.00 sec)

然后执行查询:
mysql> SELECT
group_id,
GROUP_CONCAT(content) AS result,
LENGTH(GROUP_CONCAT(content)) AS result_bytes
FROM test_data
GROUP BY group_id;
+----------+-----------------------------+--------------+
| group_id | result | result_bytes |
+----------+-----------------------------+--------------+
| 1 | item_5731,**中间省略*,item_9 | 1024 |
+----------+-----------------------------+--------------+
1 row in set, 2 warnings (0.01 sec)

结果特征非常明显:
- SQL执行成功,没有任何报错;
- 拼接结果字节数被牢牢卡在1024;
- 字符串末尾直接被切断,后面的数据全部丢失。
细心的同学可能看到查询结果下面显示了警告——但这是在命令行或日志里才会出现的。在正常业务代码的查询结果里,这些警告根本不会暴露给开发者,所以这个截断问题才尤其致命。
我们来看看这个警告具体说了什么:

没错,正是GROUP_CONCAT()函数导致的截断提示。
而一旦我们把group_concat_max_len调大,结果就恢复正常了:
mysql> SET SESSION group_concat_max_len = 102400;
Query OK, 0 rows affected (0.00 sec)

二、group_concat_max_len参数详解
1. 这是什么参数?
简单来说,group_concat_max_len是MySQL的系统级参数,专门用来限制GROUP_CONCAT函数拼接结果的最大字节长度。它不是函数语法的一部分,而是全局或会话级别的配置,这也是很多新手一上来就忽略它的原因。
2. 致命默认值
默认值:1024字节(约1KB)。注意单位是字节,不是字符。
在常用的utf8mb4编码下:
- 1个英文或数字 = 1字节
- 1个中文 = 4字节
也就是说,1024字节最多只能放大约256个汉字或1024个英文字符。只要业务数据稍微丰富一点,超限几乎是必然的结果。
3. 查看当前参数值
-- 会话级
SHOW VARIABLES LIKE 'group_concat_max_len';
-- 全局
SHOW GLOBAL VARIABLES LIKE 'group_concat_max_len';
默认安装的MySQL,执行结果肯定是1024。
4. 修改参数
直接用命令行修改,灵活性和适用场景各有不同:
- 会话级修改:只影响当前会话,适合临时调试
- 全局修改:只影响后续新建的连接,当前已有连接不受影响
-- 会话级修改
SET SESSION group_concat_max_len = 1024000;
-- 全局修改
SET GLOBAL group_concat_max_len = 1024000;
生产环境中,最稳妥的做法是在部署时就修改参数,并把配置写入my.cnf或my.ini,这样MySQL重启后也不会恢复默认值。在[mysqld]下添加:
group_concat_max_len = 1024000
三、总结
GROUP_CONCAT的核心陷阱,说到底只有一个:group_concat_max_len默认只有1024字节,拼接结果一旦超限就自动截断,而且不给任何报错。本文提供的精准复现案例,能让你直观地看到问题所在;而3种不同的修改方案,也能让你从根源上把这个坑彻底填上。
