MySQL Too many connections 报错后的排查思路
从应急处理到长期修复,整理一次线上连接数打满的完整排查过程。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-08-19 12:00:44 MySQL GROUP_CONCAT SQL 数据聚合
在写报表或者需要把一组数据拼成一个字段的时候,GROUP_CONCAT 基本绕不开。
它本身语法不复杂,但排序、去重、长度限制这些点,实际用起来还是容易踩坑。下面把我经常用到的几个场景和注意点整理一下。
语法本身不复杂。基本写法是在 GROUP_CONCAT 里面用 ORDER BY 控制拼接顺序,外面还要有 GROUP BY 指定分组。大致长这样:
SELECT
GROUP_CONCAT(
column_name
ORDER BY sort_column [ASC|DESC]
SEPARATOR '分隔符'
) AS concatenated_result
FROM table_name
GROUP BY group_column;
这里 column_name 是要拼接的字段,ORDER BY 决定组内按哪个列排序,SEPARATOR 指定分隔符,默认是逗号,GROUP BY 照常写分组字段。
很多人第一次写会漏掉外面的 GROUP BY,导致所有行拼成一行,这个错很常见。
组内排序这个功能,最典型的场景就是学生选课。想看每个学生选了哪些课,按课程名称升序拼起来,可以这样写:
SELECT
student_id,
GROUP_CONCAT(course_name ORDER BY course_name ASC) AS courses
FROM student_courses
GROUP BY student_id;
ORDER BY 只影响同一个分组内的顺序,不会改变分组本身。这个有时候会跟外层排序搞混,但其实是两回事。
如果拼接的字段里有重复值,拼出来也会重复。不想这样就在里面加个 DISTINCT:
SELECT
department_id,
GROUP_CONCAT(DISTINCT employee_name ORDER BY hire_date) AS employees
FROM staff
GROUP BY department_id;
默认分隔符是逗号,有时候内容里本身有逗号或者想用别的符号,就改 SEPARATOR。比如标签用竖线分开:
SELECT
product_id,
GROUP_CONCAT(tag_name ORDER BY tag_id SEPARATOR '|') AS tags
FROM product_tags
GROUP BY product_id;
下面拿学生课程查询完整跑一遍。建三张表:students、courses、student_courses,SQL 如下:
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE courses (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE student_courses (
student_id INT,
course_id INT,
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
插入两条学生、三门课、两条选课记录:
INSERT INTO students VALUES (1, '张三'), (2, '李四');
INSERT INTO courses VALUES (101, '数学'), (102, '英语'), (103, '物理');
INSERT INTO student_courses VALUES (1, 102), (1, 101), (2, 103);
查询时用 LEFT JOIN 把学生和课程连起来,再按学生分组拼接课程名,排序用课程名,分隔符换成分号加空格。这样结果看起来比较顺:
SELECT
s.name,
GROUP_CONCAT(c.name ORDER BY c.name ASC SEPARATOR '; ') AS courses
FROM students s
LEFT JOIN student_courses sc ON s.id = sc.student_id
LEFT JOIN courses c ON sc.course_id = c.id
GROUP BY s.id;
结果会是:
张三; 数学; 英语
李四; 物理
这个例子把排序和自定义分隔符同时用上了,基本覆盖了日常写法。
再说几个容易忽略的点。
结果长度默认最大是 1024 字节,超过的部分会被直接截断,而且不报错。线上数据量一大,查出来的字符串突然变短,很容易以为数据丢了。
调大 group_concat_max_len 可以解决,比如 SET SESSION group_concat_max_len = 1000000; 这个设置是按字节算的,具体值看业务需要。
NULL 值的默认行为是忽略。如果拼接字段里有 NULL,它不会拼出 "NULL" 字符串,而是直接跳过。
如果希望保留一个占位符,可以用 IFNULL 包一层,比如 GROUP_CONCAT(IFNULL(column_name, 'N/A') ORDER BY ...)。大部分场景忽略 NULL 是符合预期的,但如果你需要保留占位,就包一层 IFNULL。
还有个点是二次排序。有时候拼完之后想按拼接结果排序,可以在查询最后用 ORDER BY 加上别名,比如:
SELECT
department_id,
GROUP_CONCAT(employee_name ORDER BY salary DESC) AS high_earners
FROM employees
GROUP BY department_id
ORDER BY high_earners;
MySQL 允许 ORDER BY 用 SELECT 里的别名,所以这样写没问题。
整体上,GROUP_CONCAT 在报表、导出、数据透视这类场景用得很频繁,配合 ORDER BY、DISTINCT、SEPARATOR 基本能满足大多数需求。主要就是留意长度限制和 NULL 的默认行为,这两个地方出问题往往不容易立刻发现。
从应急处理到长期修复,整理一次线上连接数打满的完整排查过程。
聊聊CASE WHEN的两种语法、典型场景,以及类型、NULL、性能上那些线上跑起来才会注意到的问题。
在处理大量数据库数据时,是否常常需要提取字段的开头部分?本文将为你揭示MySQL LEFT()函数的强大之处,让你告别繁琐的手动操作。学习如何快速截取字符串前几位,并了解其在实际开发中的高效应用,如日志前缀分析、URL域名提取等,提高你的工作效率。
MySQL身份验证机制经历了从基础密码认证到插件化架构的演进,8.0版本默认采用的caching_sha2_password插件通过加盐哈希、迭代计算和双模式认证显著提升了安全性。对于传输层安全,SSL证书认证提供了端到端的加密保护。实际部署中需综合考虑兼容性与安全性,建议新系统优先使用caching_sha2_password插件并配置SSL,遗留系统可临时采用mysql_native_password插件过渡。通过密码策略强化、审计日志配置和多因素认证集成,可构建多层次的数据库安全防护体系。
MySQL SSL加密通过证书机制建立安全传输通道,核心流程包括证书生成、服务端配置、用户权限控制和客户端验证。自建环境需手动生成CA和服务器证书,云数据库通常提供一键下载证书功能。配置完成后需通过STATUS命令或查询performance_schema验证连接状态。对于高安全要求的场景,建议采用双向认证机制并定期轮换证书,同时需权衡SSL带来的性能开销(约5-10%的连接延迟)。