错误1040后出现MySQL连接:连接过多

再次错误1040 ...


技术支持收到许多有关此臭名昭著的错误的投诉: ERROR 1040: Too many connections - ERROR 1040: Too many connections过多。 问题很明显:应用程序或用户创建的连接数超出服务器允许的数量,即当前连接数超出了max_connections变量的值。



这种情况本身对于最终用户来说是个问题,但是如果您仍然无法访问服务器来诊断和纠正原因,那么一切都会变得非常糟糕。 通常,您必须完成实例并重新启动它才能恢复。


根用户无法连接! 为什么呢?


在正确配置的环境中,具有SUPER特权的用户将能够访问实例并诊断错误原因1040,原因是该错误没有足够的连接。 手册中对此进行了描述:


mysqld允许max_connections + 1个客户端连接。 为具有SUPER特权的帐户保留了一个附加连接。 如果将这些特权授予管理员而不是普通用户(不需要它们),则具有PROCESS特权的管理员也可以连接到服务器并使用SHOW PROCESSLIST诊断问题,即使连接了最大数量的没有特权的客户端也是如此。

但是很多人为应用程序或脚本的用户提供SUPER特权-由于应用程序的要求(危险!)或对后果的了解不足,然后普通用户获得了保留的连接,而管理用户(通常是root )无法连接。


如何保证对实例的访问


您可以对GDB使用著名的hack,Aurimas在 100年前就建议该错误为1040,但是现在有了更好的解决方案。 是的,必须先将它们打开。
使用Percona Server 5.5.29和更高版本以及MySQL 8.0.14和更高版本,您可以使用其他数量的连接配置另一个端口。 应用程序将不使用这些接口。 它们仅适用于数据库管理员以及运行状况监视和验证代理(请参见下面的注释)。


配置Percona服务器


从Percona Server 5.5.29开始,您可以简单地将extra_port添加到my.cnf ,下一次重新启动时,该端口将可用,并且期望数据与普通连接位于相同的bind_address 。 如果不配置extra_port变量,则默认情况下将没有其他端口。


您还可以定义extra_max_connections来指定此端口将处理的连接数。 预设值是1。


例如,我从已经在my.cnf设置extra_portextra_max_connections的实例获取了到常规用户端口的所有连接:


结果


顺便说一句,在Percona Server 8.0.14和更高版本中删除了extra_port,因为在MySQL Community中实现了具有相同功能的admin_port。 因此,如果已经定义了extra_port,则在升级到Percona Server 8.0.14或更高版本时编辑my.cnf。


在MySQL社区中进行调优


正如我所说,这需要使用WorkLog 12138的 MySQL 8.0.14。


要启用管理界面,您需要定义admin_addres ,该名称必须是管理界面将等待数据传输的唯一且唯一的(没有通配符)IPv4,IPv6,IPv4映射的地址或主机名。 如果未定义此变量,则不会启用该接口。


您仍然可以定义端口,但这不是必需的。 默认情况下,这是端口33062 。 如果该端口是空闲的,则不需要配置该值。 如果进行配置,请将两个变量都放在my.cnf[mysqld]部分中。


最后,您可以配置create_admin_listener_thread (默认情况下禁用),这将创建一个单独的线程来处理传入的连接。 在某些情况下这可能会派上用场。


另一个区别是Oracle文档说:


管理连接的数量是无限的。

(并且我们的默认值为1)。 不知道这意味着什么,但我会小心不要意外建立100万个连接。 当然,它们不受限制,但是它们仍然消耗资源。


用于监视和健康检查


方便地,当我们达到max_connections时,不仅人们可以在紧急情况下使用其他接口或端口。 代理/负载均衡器/服务发现监视系统可以连接到它。


监视脚本将能够检索图表的数据,以便稍后您可以确定许多连接来自何处。 而且,运行状况检查脚本将报告服务器的状态恶化,某些代码可能表明存在大量连接,但服务器正在管理(也就是说,它可以解决该问题,最好等一会儿再出故障)。


确保一次仅安装一个连接以进行监视和运行状况检查,以免在Percona Server中阻塞extra_max_connections,并且在MySQL中不创建一百万个线程。 也就是说,如果先前的请求或与数据库的连接仍处于活动状态,则不应再次连接脚本。


这是相同的示例,但是使用MySQL


对于Percona Server 8.0.14及更高版本,该过程将与MySQL社区的过程相同。


救命! 我需要进去,但是所有端口都忙!


如果这是您阅读此帖子的原因,请对GDB使用疯狂的hack(没有冒犯性,Aurimas,它看起来很有风险:-D)或终止实例。 幸运的是,实例几乎总是可以用SIGTERM (-15)而不是SIGKILL (-9)完美地终止。 因此,服务器将彻底停止运行,线程将有机会正常关闭。 只需按照说明进行操作即可:


1)获取PID:


 marcos.albe in ~/ pgrep -x mysqld; 650 

2)将SIGTERM发送到此PID:


 marcos.albe in ~/ kill -15 650; 

3)在错误日志中检查如何执行关机。 它看起来像这样:


 2019-07-11T13:43:28.421244Z 0 [Note] Giving 0 client threads a chance to die gracefully 2019-07-11T13:43:28.521238Z 0 [Note] Shutting down slave threads 2019-07-11T13:43:28.521272Z 0 [Note] Forcefully disconnecting 0 remaining clients 

这标志着完成过程的开始。 当您看到类似的行时,实例将完成:


 2019-07-11T13:43:31.292836Z 0 [Note] /opt/percona_server/5.7.26/bin/mysqld: Shutdown complete 

Source: https://habr.com/ru/post/zh-CN468757/


All Articles