group_concat结果被截断是因group_concat_max_len默认仅1024字节,需通过set session或修改my.cnf调大该值,并同步检查max_allowed_packet限制。

GROUP_CONCAT 拼出来的结果被截断,不是你 SQL 写错了,也不是客户端显示问题,而是 MySQL 服务端在执行时主动丢弃了超长部分——静默截断,零提示,零报错。默认 group_concat_max_len 是 1024 字节(注意:是字节,UTF-8 中一个中文占 3 字节),远不够拼接几十个 ID 或一串 JSON。
怎么确认是不是被截断了?
别猜,直接查长度和配置:
- 查当前会话限制:
SELECT @@session.group_concat_max_len; - 查实际拼接结果长度:
SELECT LENGTH(GROUP_CONCAT(your_col)) FROM your_table GROUP BY ...; - 对比两者:如果
LENGTH(...)明显大于@@session.group_concat_max_len,就是它了
常见假象:Navicat / DBeaver 显示不全,其实是服务端早就截断了;用 SELECT HEX(GROUP_CONCAT(...)) 看末尾是不是突然中断(比如最后几个字节是 2C 即逗号,后面没内容),也能佐证。
SET SESSION group_concat_max_len 为什么有时不生效?
这是最常踩的坑:命令写了,但没起作用。原因很具体:
- 漏写
SESSION关键字,只写SET group_concat_max_len = 1000000;→ MySQL 静默忽略,不报错也不生效 - 连接池(如 HikariCP、Druid)复用连接,新连接初始化时没执行
SET SESSION→ 每次拿到的仍是默认值 - 云数据库(阿里云 RDS、腾讯云 CDB)禁用
SET GLOBAL,但连SET SESSION都可能被拦截(尤其低权限账号) - 某些 ORM(如早期版本 MyBatis-Spring)在事务开启后才建连接,
SET语句执行太早,被覆盖
安全做法:在业务 SQL 前加一行 SET SESSION group_concat_max_len = 1000000;,并确保它和主查询在同一事务/同一连接中执行。
group_concat_max_len 和 max_allowed_packet 的关系
group_concat_max_len 再大也没用,如果超过 max_allowed_packet,MySQL 会直接报错:Packet for query is too large。
- 查当前值:
SELECT @@max_allowed_packet;(单位字节) - 两者必须协同调大:比如设
group_concat_max_len = 5242880(5MB),则max_allowed_packet至少也要 ≥ 5MB - 客户端也得配合:JDBC 连接串加
maxAllowedPacket=5242880,否则驱动收不到完整 packet
注意:max_allowed_packet 修改后,MySQL 服务端需重启(或 SET GLOBAL,但部分云环境不支持),客户端连接必须重建。
永久生效要改 my.cnf,但别乱设成 18446744073709551615
虽然 MySQL 允许把 group_concat_max_len 设到理论最大值,但不等于应该这么做:
- 该值是每个
GROUP_CONCAT操作独占的内存缓冲区,设太大 → 查询并发高时容易 OOM - 拼接上万行数据时,MySQL 会把所有值先 load 到内存再拼,性能陡降,可能触发磁盘临时表
- 真正需要拼超大字符串的场景(如导出全量标签、日志聚合),建议改用应用层流式处理,而非强压给 SQL
推荐值:按业务实测上限 × 1.5,比如报表最多拼 200KB,就设 group_concat_max_len = 300000;写进 my.cnf 的 [mysqld] 段,然后重启服务。别忘了同步检查 max_allowed_packet。











