作者:杨际宁
爱可生 DBA 团队成员,次要负责 MySQL 日常保护、故障解决和性能优化。对技术执着,为客户负责。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
一、背景阐明
开发反馈连 router 报错:’ERROR 1040 (HY000): Too many connections to MySQL Router’,
而后端 mysqlserver 上的连贯却只有几个。经排查发现,当连接时间超过 wait_timeout 设定的值后,8.0.29 版本 router 的 TCP 连贯并不会开释,且 8.0.30 版本的 router 仍旧存在这个问题,因而采纳降级的形式进行解决。
二、问题复现
mysqlserver 版本
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.28 |
+-----------+
1 row in set (0.01 sec)
router 版本
shell> ./mysqlrouter -V
MySQL Router Ver 8.0.30 for Linux on x86_64 (MySQL Community - GPL)
router 端口设置为 8030 和设置最大连接数 max_connections = 3 不便复现
shell> egrep 'max|port' mysqlrouter.conf
max_connections = 3
bind_port = 8030
开启 3 个会话
mysql> show processlist;
+-----+-----------------+---------------------+------+---------+--------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+-----------------+---------------------+------+---------+--------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 427243 | Waiting on empty queue | NULL |
| 146 | haha | 10.186.65.132:33324 | NULL | Sleep | 184 | | NULL |
| 147 | haha | 10.186.65.132:33326 | NULL | Sleep | 14 | | NULL |
| 148 | haha | 10.186.65.132:33328 | NULL | Sleep | 9 | | NULL |
| 149 | root | localhost | NULL | Query | 0 | init | show processlist |
+-----+-----------------+---------------------+------+---------+--------+------------------------+------------------+
5 rows in set (0.00 sec)
所有会话设置 wait_timeout = 10,超时断开连接
MySQL [(none)]> show databases; set wait_timeout=10;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]>
查看会话(客户端曾经断开连接,但不做任何操作将占有 router 的连贯)
mysql> show processlist;
+-----+-----------------+-----------+------+---------+--------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+-----------------+-----------+------+---------+--------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 427509 | Waiting on empty queue | NULL |
| 157 | root | localhost | NULL | Query | 0 | init | show processlist |
+-----+-----------------+-----------+------+---------+--------+------------------------+------------------+
2 rows in set (0.00 sec)
新建连贯报错
shell> mysql -uhaha -p1 -h10.186.65.132 -P8030
ERROR 1040 (HY000): Too many connections to MySQL Router
查看 router 和 mysqlclient 的连贯,并未开释
[root@router ~]# netstat -lntpa |grep 8030
tcp 0 0 0.0.0.0:8030 0.0.0.0:* LISTEN 15045/./mysqlrouter
tcp 0 0 10.186.65.132:8030 10.186.65.137:56308 ESTABLISHED 15045/./mysqlrouter
tcp 0 0 10.186.65.132:8030 10.186.65.137:56312 ESTABLISHED 15045/./mysqlrouter
tcp 0 0 10.186.65.132:8030 10.186.65.137:56310 ESTABLISHED 15045/./mysqlrouter
[root@mysql ~]# netstat -lntpa |grep 8030
tcp 0 0 10.186.65.137:56308 10.186.65.132:8030 ESTABLISHED 3992/mysql
tcp 0 0 10.186.65.137:56310 10.186.65.132:8030 ESTABLISHED 3990/mysql
tcp 0 0 10.186.65.137:56312 10.186.65.132:8030 ESTABLISHED 3935/mysql
三、抓包剖析
先看看 mysqlserver 端的包有没有什么异样
三次握手
超时断开连接
进行四次挥手,发现没有收到 router 说拜拜的信号
看下 router 端的抓包,能够看到确实没有说拜拜
没有收到 router 说拜拜的信号,router 的连贯应该为 close_wait 的状态
那么 mysqlserver 端没有收到 router 回复的 [FIN, ACK],是不是只能始终在 FIN_WAIT2 的状态呢?TCP 没有对这个状态的解决,然而 Linux 能够调整 tcp_fin_timeout 参数来设置一个超时工夫。
那么 router 和 mysql_client 的连贯呢?能够看到没有任何一方发送断开的申请
因而就会产生 mysqlserver 端曾经断开了所有会话,然而 router 和 mysqlclient 并未断开,导致新建连贯无奈通过 router 连贯后端的 mysqlserver
8.0.28 版本的 router 并不会呈现上述问题,能够看到 mysqlserver 端发送断开连接申请的时候,router 回复了 [FIN, ACK],看一下 router 端的抓包
至于为什么四次挥手只抓到 3 个包,是因为把第 2,3 个包合并一起发送了,具体能够参考 RFC793 的 3.5 大节。
来看一下 mysqlserver 端的抓包
怎么 mysqlserver 端抓了 4 个包?别被蛊惑,其实 643 的包是 641 的回包
到这里,router 到 mysqlserver 端的连贯是能够失常敞开的。
再看一下 8.0.28 版本的 router 和 mysqlclient 的连贯呢,mysqlclient 端的抓包(测试端口:6446)
能够看到 router 被动发送了断开的申请。
四、总结
测试发现 8.0.29 和 8.0.30 版本的 router 都会有此问题。
8.0.28 和 8.0.21 版本的 router 通过测试是不存在此问题的,其余版本有趣味的能够测试一下。
可能和 router 8.0.29 版本的新性能 ‘Added connection pooling functionality to reuse server-side connections’ 有关系。
最初,因集体能力无限,如有错漏之处,敬请斧正。