MySQL 连接数:为什么你的服务器总“Too many connections”?连接池的配置和优化

文章目录

    查看 MySQL 的当前连接数是排查性能瓶颈和配置连接池时的基本功。
    所以记录一下可能用到的查询命令。以下是基于 MySQL 8.0 的测试:

    当前有多少个客户端连着数据库

    当前打开的连接数:

    > SHOW STATUS LIKE 'Threads_connected';
    +-------------------+-------+
    | Variable_name     | Value |
    +-------------------+-------+
    | Threads_connected | 17    |
    +-------------------+-------+
    1 row in set (0.01 sec)
    

    查看详细的连接列表

    > SHOW FULL PROCESSLIST;
    +-------+-----------------+-----------------+----------------+---------+----------+------------------------+-----------------------+
    | Id    | User            | Host            | db             | Command | Time     | State                  | Info                  |
    +-------+-----------------+-----------------+----------------+---------+----------+------------------------+-----------------------+
    |     5 | event_scheduler | localhost       | NULL           | Daemon  | 98589253 | Waiting on empty queue | NULL                  |
    | 20740 | user1           | localhost:54994 | database1      | Sleep   |      470 |                        | NULL                  |
    | 20741 | user1           | localhost:55450 | database1      | Sleep   |      470 |                        | NULL                  |
    | 20918 | user1           | localhost:49080 | database3      | Sleep   |      470 |                        | NULL                  |
    | 21858 | user1           | localhost:47582 | database2      | Sleep   |      470 |                        | NULL                  |
    | 21859 | user1           | localhost:47734 | database2      | Sleep   |      470 |                        | NULL                  |
    | 24081 | user1           | localhost       | db5            | Query   |        0 | init                   | SHOW FULL PROCESSLIST |
    +-------+-----------------+-----------------+----------------+---------+----------+------------------------+-----------------------+
    18 rows in set (0.00 sec)
    

    字段说明:

    • Command: 连接状态(如 Sleep 表示空闲,Query 表示正在查)
    • Time: 该状态持续的时间(秒)。

    可以看到目前的大部分连接处于 Sleep 状态,说明这些连接是空闲的,没有在执行查询。

    而且每个独立的数据库都有两个 sleep 状态的连接,说明我的 golang gorm 默认配置是 MaxIdleConns 为 2。
    即使没有查询任务,连接池也会保持 2 个空闲连接。但是对于高并发的场景,2 个空闲连接可能不够用。
    原因是在高并发结束后,多出来的连接会被立即关闭,等下次请求来时又要重新握手。

    当前正在执行查询的连接数

    通常远小于 connected,如果这个值很高,说明数据库压力极大

    > SHOW STATUS LIKE 'Threads_running';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | Threads_running | 2     |
    +-----------------+-------+
    1 row in set (0.00 sec)
    

    最大连接数限制

    > SHOW VARIABLES LIKE 'max_connections';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_connections | 151   |
    +-----------------+-------+
    1 row in set (0.00 sec)
    

    默认是 151,可以根据需要调整这个值,避免连接数过多导致拒绝服务。

    同时也要对应的限制 golang gorm 的最大连接数,当流量激增时,程序会尝试开启成千上万个连接,直接超出数据库限制,导致报错 Too many connections。

    历史最高连接数(峰值)

    这个值记录了自 MySQL 启动以来的历史最大并发连接数。如果这个值远低于你的连接池总和,说明你的连接池设置得太大了,浪费资源。

    > SHOW STATUS LIKE 'Max_used_connections';
    +----------------------+-------+
    | Variable_name        | Value |
    +----------------------+-------+
    | Max_used_connections | 18    |
    +----------------------+-------+
    1 row in set (0.00 sec)
    

    一个 mysql 连接会占用多少内存

    • 空闲 (Idle)连接状态:2MB ~ 5MB,仅包含线程栈和基础缓冲区。
    • 普通查询连接状态:5MB ~ 10MB,包含了一些基础的读取缓冲区。
    • 重度查询连接状态(排序/大表关联):32MB ~ 128MB+,如果 SQL 写得烂,且 sort_buffer 设置得大,内存会迅速飙升。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式