2016-06-13 167 views
5

最近在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 

回答

1

我们在使用mysql 5.7.13的Ubuntu 16.04系统上遇到同样的问题。我们systemd增加我们的最大打开文件参数是这样的:

/etc/systemd/system/mysql.service.d/10-ulimit.conf

[Service] 
LimitNOFILE=1000000 

到目前为止,这个问题并没有发生再次。也许mysql现在需要更多的文件描述符。

+0

只是单挑向上与DNF更新MariaDB的时候在我的FC24系统中,systemd文件被覆盖,并且这个问题复发。 – glyph

+0

不幸的是,这个修复在这里不起作用。我在使用MySQL 5.7.17的新鲜Ubuntu 16.04和Ubuntu 16.10实例上遇到了这个错误。 (顺便说一句,我认为有必要先创建mysql.service文件夹并运行'systemctl daemon-reload')。 – mahemoff

0

升级到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; 
} 
+0

尽管丑陋的社会解决方法仍然很好,所以我推荐给任何碰到这个问题的人。看起来这是一段时间以来的问题,并且只能影响一些环境(请参阅下面的Google和@Roel)。 –

+0

更新。随着社会的变通办法,我仍然看到一些循环产生这些错误,但他们似乎最终终止,所以系统是广泛稳定的。 –

1

研究之了一下,发现以下;

  1. 目前在MariaDB的也

    https://lists.launchpad.net/maria-discuss/msg03060.html https://mariadb.atlassian.net/browse/MDEV-8995

  2. 的Percona服务器/ Percona的XtraDB集群

    https://groups.google.com/forum/#!topic/percona-discussion/Tu0S2OvYqKA

  3. 老臭虫从2010/2012

    https://bugs.mysql.com/bug.php?id=48929 http://lists.mysql.com/commits/96472

  4. 一些有趣的信息(不应该发生)

    https://lists.mysql.com/mysql/97275

[我为Percona的工作]

2

我发现这个问题(或者可能是一个问题)。下面是使用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。希望它可以帮助反正

尼克

+0

我有完全相同的问题(日志充斥着“坏文件描述符”消息和MySQL不工作),并搜索了很多,直到我找到这篇文章。在我的情况下,fail2ban出于某种原因在/etc/hosts.deny中添加了127.0.0.1以彻底搞乱系统! 只要我删除它(并将localhost添加到/etc/hosts.allow以防止将来发生这种情况),事情就会恢复正常。 故事的士气:作为一项预防措施,将127.0.0.1添加到/etc/hosts.allow只是为了确保fail2ban不会妨碍您! –

+0

我向hosts.allow和hosts.deny添加了一些mysqld选项,然后当我发现MySQL Workbench无法正确连接时删除它们。在问题中提到的消息充斥了我的error.log文件,直到磁盘空间不足。我停止了mysql服务,压缩了该日志文件并重新启动。现在一切都好了。谢谢。 – user208145

相关问题