MySQL - 0 [错误]接受错误:错误的文件描述符
最近在Debian(Debian 3.2.78-1 x86_64 GNU/Linux)上升级到MySQL 5.7.12,并且每隔几个小时。这是收到了大量的系统日志和mysql.log:MySQL - 0 [错误]接受错误:错误的文件描述符
2016-06-13T18:05:20.261209Z 0 [ERROR] Error in accept: Bad file descriptor
MySQL的信息: 的MySQL版本14.14 DISTRIB 5.7.12-5,使用Debian的Linux-GNU(x86_64的)6.2
的my.cnf的mysqld部分的饮片,可以指导调整值有一些帮助:
[mysqld]
max_allowed_packet = 64M
thread_stack = 256K
thread_cache_size = 8
max_connections = 150
max_connect_errors = 10000
connect_timeout = 30
wait_timeout = 86400
table_open_cache = 2048
open_files_limit = 65535
query_cache_limit = 4M
query_cache_size = 128M
query_cache_type = 1
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
# * InnoDB
innodb_file_per_table
innodb_buffer_pool_instances=2
innodb_buffer_pool_size=2G
thread_pool_size = 24
我们在使用mysql 5.7.13的Ubuntu 16.04系统上遇到同样的问题。我们systemd增加我们的最大打开文件参数是这样的:
/etc/systemd/system/mysql.service.d/10-ulimit.conf
[Service]
LimitNOFILE=1000000
到目前为止,这个问题并没有发生再次。也许mysql现在需要更多的文件描述符。
升级到Percona Cluster 5.7.14-26.17-1.trusty后,我遇到同样的问题。
ulimit.conf建议并没有帮助,并且我通过编辑/etc/security/limits.conf和/ etc/sysctl确保有足够的文件句柄。 CONF。
我可以很容易地通过telnetting来发布3306然后断开连接;服务器然后进入旋转日志记录此错误。
对此,一个可怕的解决方法是在我的环境中看起来很有前途,它避免在端口3306上使用TCP连接,而是使用unix套接字。
您可以代理从3306端口到插座通过改变/etc/mysql/my.cnf的端口号,然后使用socat
nohup socat TCP4-LISTEN:3306,fork UNIX-CONNECT:/var/run/mysqld/mysqld.sock&
如果我然后telnet在端口3306和断开,我不能挑起问题。我打算回顾一下这段时间的表现如何。
FWIW,代码看起来好像预计,有时会发生:
for (uint retry= 0; retry < MAX_ACCEPT_RETRY; retry++)
{
socket_len_t length= sizeof(struct sockaddr_storage);
connect_sock= mysql_socket_accept(key_socket_client_connection, listen_sock,
(struct sockaddr *)(&cAddr), &length);
if (mysql_socket_getfd(connect_sock) != INVALID_SOCKET ||
(socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
break;
}
if (mysql_socket_getfd(connect_sock) == INVALID_SOCKET)
{
/*
accept(2) failed on the listening port, after many retries.
There is not much details to report about the client,
increment the server global status variable.
*/
connection_errors_accept++;
if ((m_error_count++ & 255) == 0) // This can happen often
sql_print_error("Error in accept: %s", strerror(errno));
if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
sleep(1); // Give other threads some time
return NULL;
}
尽管丑陋的社会解决方法仍然很好,所以我推荐给任何碰到这个问题的人。看起来这是一段时间以来的问题,并且只能影响一些环境(请参阅下面的Google和@Roel)。 –
更新。随着社会的变通办法,我仍然看到一些循环产生这些错误,但他们似乎最终终止,所以系统是广泛稳定的。 –
研究之了一下,发现以下;
-
目前在MariaDB的也
https://lists.launchpad.net/maria-discuss/msg03060.html https://mariadb.atlassian.net/browse/MDEV-8995
-
的Percona服务器/ Percona的XtraDB集群
https://groups.google.com/forum/#!topic/percona-discussion/Tu0S2OvYqKA
-
老臭虫从2010/2012
https://bugs.mysql.com/bug.php?id=48929 http://lists.mysql.com/commits/96472
-
一些有趣的信息(不应该发生)
[我为Percona的工作]
我发现这个问题(或者可能是一个问题)。下面是使用strace在mysqld的摘录:
...
socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 20
write(2, "2017-01-29T22:22:45.433033Z 0 [N"..., 72) = 72
setsockopt(20, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(20, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0
bind(20, {sa_family=AF_INET6, sin6_port=htons(3306), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
listen(20, 70) = 0
fcntl(20, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(20, F_SETFL, O_RDWR|O_NONBLOCK) = 0
...
accept(20, {sa_family=AF_INET6, sin6_port=htons(58332), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 37
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTORER|SA_RESTART, 0x7f3ddeac84b0}, {SIG_DFL, [], 0}, 8) = 0
getpeername(37, {sa_family=AF_INET6, sin6_port=htons(58332), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
getsockname(37, {sa_family=AF_INET6, sin6_port=htons(3306), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
open("/etc/hosts.allow", O_RDONLY) = 38
fstat(38, {st_mode=S_IFREG|0644, st_size=589, ...}) = 0
read(38, "# /etc/hosts.allow: list of host"..., 4096) = 589
read(38, "", 4096) = 0
close(38) = 0
open("/etc/hosts.deny", O_RDONLY) = 38
fstat(38, {st_mode=S_IFREG|0644, st_size=704, ...}) = 0
read(38, "# /etc/hosts.deny: list of hosts"..., 4096) = 704
close(38) = 0
socket(PF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 38
connect(38, {sa_family=AF_LOCAL, sun_path="/dev/log"}, 110) = 0
sendto(38, "<36>Jan 29 14:23:08 mysqld[13052"..., 72, MSG_NOSIGNAL, NULL, 0) = 72
shutdown(20, SHUT_RDWR) = 0
close(20) = 0
poll([{fd=20, events=POLLIN}, {fd=22, events=POLLIN}], 2, -1) = 1 ([{fd=20, revents=POLLNVAL}])
accept(-1, 0x7ffe6ebd7160, 0x7ffe6ebd70fc) = -1 EBADF (Bad file descriptor)
write(2, "2017-01-29T22:23:08.109451Z 0 [E"..., 75) = 75
... rinse and repeat *REALLY* fast!
在我的系统锁定下来我无意中拍摄的mysqld出既hosts.allow和hosts.deny中的tcp_wrappers的。看起来,在检查hosts.allow和hosts.deny之后,mysqld关闭并按照您的预期关闭套接字。然而,它们立即开始轮询(现在不存在的)活动插座。
我只是做了另一个测试,我的tcp_wrappers配置正确。当我从授权主机连接时,一切都很好;但是,当我从阻塞的地址连接时发生同样的问题。基于此,我建议使用其他工具来保护mysqld并使您的tcp_wrappers配置比防火墙更开放。这就是说,错误应该仍然是固定的!
这个修复程序还没有经过时间的测试,所以像往常一样,YMMV。希望它可以帮助反正
尼克
我有完全相同的问题(日志充斥着“坏文件描述符”消息和MySQL不工作),并搜索了很多,直到我找到这篇文章。在我的情况下,fail2ban出于某种原因在/etc/hosts.deny中添加了127.0.0.1以彻底搞乱系统! 只要我删除它(并将localhost添加到/etc/hosts.allow以防止将来发生这种情况),事情就会恢复正常。 故事的士气:作为一项预防措施,将127.0.0.1添加到/etc/hosts.allow只是为了确保fail2ban不会妨碍您! –
我向hosts.allow和hosts.deny添加了一些mysqld选项,然后当我发现MySQL Workbench无法正确连接时删除它们。在问题中提到的消息充斥了我的error.log文件,直到磁盘空间不足。我停止了mysql服务,压缩了该日志文件并重新启动。现在一切都好了。谢谢。 – user208145
只是单挑向上与DNF更新MariaDB的时候在我的FC24系统中,systemd文件被覆盖,并且这个问题复发。 – glyph
不幸的是,这个修复在这里不起作用。我在使用MySQL 5.7.17的新鲜Ubuntu 16.04和Ubuntu 16.10实例上遇到了这个错误。 (顺便说一句,我认为有必要先创建mysql.service文件夹并运行'systemctl daemon-reload')。 – mahemoff