一次因为超过最大连接数登录陆限制-爱可生

原标题:一次因为超过最大连接数登录陆限制-爱可生

一次因为超过最大连接数登录陆限制-爱可生
文章图片
现象
在测试某功能时 , 将mysql的最大连接数设置为120 , 使用sysbench并发200插入数据 ,
上述错误是预期内的结果 , 因为sysbench的200个并发超过了mysql实例最大连接数;

一次因为超过最大连接数登录陆限制-爱可生
文章图片
随后 , 修改sysbench并发数为100(小于最大连接数) , 再次插入数据 , 失败报错 , 并发数已经小于最大连接数了 , 为什么还报错 , 报错信息如下:
使用用户test单独登录实例 , 和上面报一样的错误:

一次因为超过最大连接数登录陆限制-爱可生
文章图片
之前正常的可以登录的用户test , 现在无法登陆了 。

一次因为超过最大连接数登录陆限制-爱可生
文章图片
原因和解决方法
起初 , 并不了解是什么原因造成的登录失败 。 查询官网文档了解到 , 是用户的错误的连接数超过了设置的最大值 , 这个最大值参数是max_connect_errors 。
解决方法很简单:执行flushhosts
分析
对于这个参数max_connect_errors之前并不了解 , 查阅网上文档提到 , 使用错误密码多次登陆并不能模拟失败连接 。 尝试将此参数修改为2 , 然后使用错误密码登录2次 , 后续再登录依然成功 。 看来使用错误密码确实不能模拟失败连接 。
查阅官网文档了解到 , 在PerformanceSchema库表host_cache里会保存客户端的连接信息 , 其中字段SUM_CONNECT_ERRORS就是记录连接的错误次数 , 一旦SUM_CONNECT_ERRORS的值达到max_connect_errors设定的值 , 来自此客户端的连接就会被阻止 。
SUM_CONNECT_ERRORS的官网描述:Thenumberofconnectionerrorsthataredeemed“blocking”(assessedagainstthemax_connect_errorssystemvariable).Onlyprotocolhandshakeerrorsarecounted,andonlyforhoststhatpassedvalidation(HOST_VALIDATED=YES).
可以看到这里指的是协议握手错误的次数 。
下面使用telnet来模拟协议的握手错误次数:
配置最大错误连接错误数为2 , 查看库表PerformanceSchema.host_cache的SUM_CONNECT_ERRORS
这里SUM_CONNECT_ERRORS初始值为0;

一次因为超过最大连接数登录陆限制-爱可生
文章图片
注:另一个参数count_authentication_errors是尝试错误密码登录的次数(这里的2就是之前尝试错误密码登录的次数) 。
在客户端主机上使用telnet尝试2次端口探测 ,
再次查看该主机的SUM_CONNECT_ERRORS变成了2 。

一次因为超过最大连接数登录陆限制-爱可生
文章图片
此时问题复现 , 客户端登录实例被拒绝 , 因为错误连接次数达到了最大值2 。

一次因为超过最大连接数登录陆限制-爱可生
文章图片
回到本文最开始的问题 , sysbench并发200超过最大连接数max_connections=120时 ,

一次因为超过最大连接数登录陆限制-爱可生
文章图片
由于max_connect_errors的缺省值是100 , sysbench并发200造成了109个错误连接 , 这就超过了错误连接的最大值 , 所以后续连接就报错了 。

一次因为超过最大连接数登录陆限制-爱可生
文章图片
另外 , 为什么错误连接数SUM_CONNECT_ERRORS是109 , 是因为此环境实例已经存在来自其他客户端的11个正常连接(通过showprocesslist可见) , 那么只剩下120-11=109个可用连接 , sysbench的200个并发 , 只接受了109个然后就协议握手失败 , 所以造成了109个错误连接 。
延伸
官网提到错误连接指的是协议的握手失败次数 , 并未明确说明是哪个协议 , 是TCP/IP还是应用层的MySQL协议?
对于TCP/IP通信 , 首先是TCP协议的三次握手 , 因为客户端已经成功收到了服务端返回的报错:error1040:Toomanyconnections , TCP握手已经成功完成了 , 所以这里的协议应该指的是MySQL的握手协议 。
这里可以通过抓包来验证:
上述前三个包是完整的TCP握手协议包 , 已经完成了TCP的握手协议 , 后面MySQL协议服务端发送完HandShake信息之后双方就关闭了连接 , 客户端并未继续发送登录认证包 , 造成MySQL的协议握手失败 。 所以这里指的是MySQL的协议握手失败次数 。

一次因为超过最大连接数登录陆限制-爱可生
文章图片
一次因为超过最大连接数登录陆限制-爱可生】针对上面利用telnet来模拟协议握手失败的例子 , 由于telnet只是发送了TCP的握手包 , 并不会发送MySQL登录认证包 , 服务器端等待10秒(mysql的connect_timeout=10)就关闭了连接 , 所以才造成MySQL的握手失败 。