出现 unauthenticated user Connect 怎么办

导读

什么情况下会出现 unauthenticated user,该怎么办?

前几天,我的朋友小明同学微信上找到我,说mysql错误日志很频繁的打印下面的日志:

Aborted connection 16021014 to db: 'unconnected' user: 'unauthenticated'
 host: 'connecting host' (Can't get hostname for your address)

我的第一反应是可能有几种情况:
1、开了线程池,且thread_pool_size可能开太小了,或者thread_pool_stall_limit采用默认值(也就是500)。如果有较高并发请求,且每次请求的SQL效率都比较低的话,是有可能会造成线程池切换响应不过来,有些连接请求会失败。

2、可能有来自外部的不安全扫描、探测,就是简单的测试下3306端口是否能连通,以及探测mysql版本号,想借此寻求机会入侵。这种情况,有较大可能性是mysql不是只绑定到内部网卡,在公网网卡上也绑定了。

3、应用端疯狂连接,mysql端响应较慢,主机名反解析较慢导致。

4、在mysql的前端有监控、探测程序,时不时要检测其是否存活。比如zabbix agent会定期连接mysql获取监控数据,也有可能是高可用组件或SLB(Server Load Balancer,服务器负载均衡)组件定期探测mysql是否存活。

5、前端某些应用程序配置了错误的账号密码。不过这种情况会报告类似 Access denied 这样的日志,和本案例中的日志不一样。

再交代下这个mysql实例的大概情况:
– 当前系统负载和mysqld进程负载都不高。
– 采用Percona-Server-5.6.34版本,且开启了线程池(thread pool)。
– 这是一个游戏后端数据库。
– 游戏程序端采用连接池+长连接方式(这…都长连接了还开线程池嘎哈),平时保持的连接数约有将近1000个。

交代完背景,我们就照着上面的几个可能性逐个排查吧。

1、线程池

线程池相关的配置如下:

thread_handling = pool-of-threads
thread_pool_high_prio_mode = transactions
thread_pool_high_prio_tickets = 4294967295
thread_pool_idle_timeout = 60
thread_pool_max_threads = 100000
thread_pool_oversubscribe = 3
thread_pool_size = 16
thread_pool_stall_limit = 500

可以看到,thread_pool_sizethread_pool_stall_limit 这两个选项看起来都不是太合理,先尝试调整成:

thread_pool_size = 128
thread_pool_stall_limit = 10

调整完后,继续观察,发现无果。看来不是线程池设置不合理导致的了,继续下一个疑点。

2、外部扫描、探测

这个实例只绑定了内部网卡,并未对公网开放,执行了 netstat -nat 查看也未发现有看起来比较怪异的源IP连接。
跳过。

3、主机名反解析慢导致

本例中,不是这个原因引起的,因为已经设置了 skip_name_resolve = 0

4、前端有监控、探测程序

首先检查zabbix agent程序,账号、密码配置是正确的,还不死心,干脆把agent程序先临时停一下,发现也还是跟它没关系。跳过。

看来大概率是有什么高可用或SLB组件做存活探测了。一问之下,果真是用了某公有云的SLB服务,它会频繁(约1秒3、4次)的探测mysql端口。事实上,这个情况以前也遇到过,甚至还发生过因为SLB探测太过频繁,结果被mysql给blocked的“故障”,所以后来要求把选项 max_connect_errors 的值加大,检查了下,还真是设置很大:

max_connect_errors = 100000000000

把SLB服务先临时停一下,开头所说的告警日志果真就不再产生了。找到问题原因所在。

解决问题

在本案中,因为应用程序已经采用了连接池+长连接,因此也就没必要启用线程池了,所以就先把线程池给关了吧。

神奇的一幕发生了,关闭线程池之后,在SLB服务仍旧启用的情况下,上述日志居然不再产生了,这特么的…手动黑人问号脸???.jpg

经过测试验证,发现的确是只要开了线程池(采用Percona版本),在这种情况下就会一直发出告警,好吧,忍了,关掉就好了。

同时,因为长连接约有1000个,因此调整 thread_cache_size = 2000
至此,这个问题算是暂时解决了(其实只算解决了一半)。

后记

我又在MySQL 5.6和8.0的环境下做了测试,用 telnet 或 nc 模拟探测 3306 端口的行为,发现确实是会出现类似下面的状态:

| 10165 | unauthenticated user | 127.0.0.1:59004 |  | Connect | 3 | login |

此外,错误日志上也会打印类似下面的内容:

...[Note]...Got an error reading communication packets
...[Note]...Got packets out of order

顺便对公有云厂商们提个建议,SLB服务可以增加针对mysql数据库的探测方式,比如下面这样用:

[root@yejr.me ~]# mysqladmin -hx -ux -px ping
mysqld is alive

这样就不会导致日志里记录大量的Note事件了。

全文完。


知数堂「MySQL优化课」第17期已发车,课程从第15期就升级成MySQL 8.0版本了,现在上车刚刚好,扫码开启MySQL 8.0的修行之旅吧。

另外,《MySQL性能优化精编课》已上线,本课程讲解读几个MySQL性能优化的核心要素:合理利用索引,降低锁影响,提高事务并发度。戳此自动拼团,组团价仅需78元

Percona Thread Pool性能基准测试

MySQL从5.5.16开始,在MySQL的商业化版本中将Thread Pool作为plugin提供官方功能支持。后来MariaDB也实现了这一功能,Percona也跟进实现了。从这几天对Percona 5.6.16版本做了下thread pool对比测试,试图找到较为合适的配置参数。

下面是几个测试模式对比:

模式 配置参数
Percona 5.6.16-nothp 未开启 thread pool 模式
CASE0-thp(128)-oversub(16)-max(2048) thread_handling = pool-of-threads
thread_pool_size = 128
thread_pool_oversubscribe = 16
thread_pool_max_threads = 2048
CASE1-thp(default) thread_handling = pool-of-threads
其他默认设置
CASE2-thp(default)-oversub(10) thread_handling = pool-of-threads
thread_pool_oversubscribe = 10
其他默认设置
CASE3-thp(default)-oversub(10)-max(10000) thread_handling = pool-of-threads
thread_pool_oversubscribe = 10
thread_pool_max_threads = 100000
其他默认设置
CASE4-thp(default)-oversub(16) thread_handling = pool-of-threads
thread_pool_oversubscribe = 16
其他默认设置
CASE5-thp(128)-oversub(16)-max(100000) thread_handling = pool-of-threads
thread_pool_size = 128
thread_pool_oversubscribe = 16
thread_pool_max_threads = 100000

仍然采用tpcc-mysql这个测试工具,基准值:

测试Warehouse数: 100
warmup time: 60s
run time: 1200s
并发线程数: 64 ~ 1920

测试环境信息:

测试机 DELL PE R710
CPU E5620  @ 2.40GHz(4 core, 8 threads, L3 Cache 12 MB) * 2
内存 32G(4G * 8)
RAID卡 PERC H700 Integrated, 512MB, BBU, 12.10.1-0001
系统 Red Hat Enterprise Linux Server release 6.4 (Santiago)
内核 2.6.32-358.el6.x86_64 #1 SMP
raid级别 raid 0
文件系统 xfs
硬盘 SSD: Intel 520系列SSD, 800G * 1

Percona版本号:5.6.16-64.2-rel64.2-log Percona Server with XtraDB (GPL), Release rel64.2, Revision 569,Percona相关的关键配置有:

innodb_buffer_pool_size = 26G
innodb_flush_log_at_trx_commit = 1

测试脚本可参考:MySQL压力测试经验

测试结果见下:

Percona-Thread-Pool测试-20140701.png

针对这个测试结果,我们可以得到一些结论:

 

1、通常地,只需要开启 pool-of-threads 模式就可以;
2、可以根据实际压力情况,适当调整 thread_pool_oversubscribe 选项以提升 TPS,这个选项值设置范围一般在 3~20;
3、thread-pool-size默认值是逻辑CPU个数,最大值是 128,不建议调整或显式设置,如果显式设定 thread-pool-size 的值,可能会带来反效果;
4、thread_pool_max_threads 默认值是 100000,强烈不建议修改。

综上,对于Thread Pool,我们一般建议设置下面2个选项就足够了:

thread_handling = pool-of-threads
thread_pool_oversubscribe = 10 #这个值建议在3~20间,不清楚的话,无需设置

备注:启用Thread Pool后,想要终止某个查询的话,要这么写KILL QUERY connection_id,而不是写成 KILL connection_id,否则就会导致整个连接被KILL。

如果还有什么问题,欢迎加入我的QQ群(272675472)讨论。