group_concat默认截断是因group_concat_max_len默认值为1024字节,非bug而是设计;需通过set session/global或配置文件调整,并注意max_allowed_packet限制及内存性能风险。

GROUP_CONCAT 默认只允许 1024 字节,不是 bug 是设计
这不是你 SQL 写错了,是 MySQL 服务端变量 group_concat_max_len 的默认值就是 1024 —— 单位是字节,不是字符。UTF-8 下一个中文占 3 字节,一个 emoji 可能占 4 字节,拼几十个字段就撞上了。
它不报错、不警告,只是静默丢掉超长部分。你查 SELECT GROUP_CONCAT(name) 看着像少了一半数据,其实是因为后半截被砍掉了。
- 用
SELECT LENGTH(GROUP_CONCAT(...))能看到实际拼出多少字节,和SELECT @@group_concat_max_len对比就能确认是否被截 -
CHAR_LENGTH()返回字符数,LENGTH()才是字节数 —— 别用错 - 分隔符(比如逗号、空格)也会计入总长度,哪怕你写
SEPARATOR '',空字符串本身不占,但逻辑上仍参与拼接流程
SET SESSION 不生效?大概率是漏写了作用域关键字
执行 SET group_concat_max_len = 1000000 是无效的 —— MySQL 会静默忽略。必须明确指定作用域:
- 当前连接生效:
SET SESSION group_concat_max_len = 1000000 - 新连接生效(需 SUPER 权限):
SET GLOBAL group_concat_max_len = 1000000 - 执行完立刻验证:
SELECT @@session.group_concat_max_len
云数据库(如阿里云 RDS、腾讯云 CDB)通常禁用 SET GLOBAL,得走控制台参数模板修改,且改完要重启实例。
调大了 group_concat_max_len 还失败?看看 max_allowed_packet
group_concat_max_len 再大,也跨不过 max_allowed_packet 这道硬门槛。后者限制单次网络包大小,GROUP_CONCAT 结果作为查询返回值,必须装得进这个 packet。
- 查当前值:
SELECT @@max_allowed_packet(单位字节) - 如果设了
group_concat_max_len = 5242880(5MB),但max_allowed_packet = 4194304(4MB),就会直接报错:Packet for query is too large - 客户端也要配合:JDBC URL 加
maxAllowedPacket=5242880,否则驱动层先拦住
别盲目设成 100MB,内存和性能风险真实存在
MySQL 执行 GROUP_CONCAT 时,会把所有匹配行的字段值一次性加载进内存再拼接。数据量大时:
- 可能触发
Out of memory,尤其在小内存服务器或高并发场景 - 拖慢整个查询,影响其他连接
- 连接池(如 HikariCP)复用旧连接时,若没在初始化 SQL 里跑
SET SESSION,每次取到的仍是默认 1024
真正稳妥的做法是:先估算业务侧最大拼接长度(字段平均字节数 × 最大行数 + 分隔符开销),再留 20% 余量设置 group_concat_max_len,而不是无脑设到理论最大值。











