2016-06-13 4 views
5

Vor kurzem auf MySQL 5.7.12 auf einem Debian (Debian 3.2.78-1 x86_64 GNU/Linux) aktualisiert und laufen auf dem Server alle paar Stunden hängen .MySQL - 0 [ERROR] Fehler in accept: Ungültiger Dateideskriptor

2016-06-13T18:05:20.261209Z 0 [ERROR] Error in accept: Bad file descriptor

MySQL info:: Dies ist immer in der syslog und mysql.log überflutet mysql Ver 14.14 Distrib 5.7.12-5, für debian-linux-gnu (x86_64) mit 6,2

Stücke von my.cnfmysqld Abschnitt, der etwas Hilfe auf Tweaking Werte führen können:

[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 

Antwort

1

Wir hatten das gleiche Problem auf einem Ubuntu 16.04 System mit MySQL 5.7.13. Wir haben unsere max geöffneten Dateien Parameter in systemd wie folgt aus:

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

[Service] 
LimitNOFILE=1000000 

Bisher ist die Frage nicht der Fall war nochmal. Vielleicht braucht MySQL jetzt mehr Dateideskriptoren.

+0

Nur ein Heads-Up- Auf meinem FC24-System, wenn MariaDB mit DNF Aktualisierung wurde die systemd Datei überschrieben und dieses Problem wieder aufgetreten. – glyph

+0

Leider hat dieser Fix hier nicht funktioniert. Ich habe diesen Fehler bei frischen Ubuntu 16.04 und Ubuntu 16.10 Instanzen mit MySQL 5.7.17 festgestellt. (BTW Ich denke, dass es notwendig ist, den Ordner mysql.service zuerst zu machen und 'systemctl daemon-reload' auszuführen). – mahemoff

0

Ich habe das gleiche Problem nach dem Upgrade auf Percona Cluster 5.7.14-26.17-1.trusty.

Der Vorschlag ulimit.conf hilft nicht, und ich habe sichergestellt, dass es genügend Dateihandles gibt, soweit ich das beurteilen kann, indem ich /etc/security/limits.conf und/etc/sysctl bearbeite. Konf.

Ich kann dies leicht reproduzieren, indem ich telnett, um 3306 zu posten und dann zu trennen; Der Server geht dann in eine Rotation, die diesen Fehler protokolliert.

Eine schreckliche Problemumgehung für diese, die in meiner Umgebung vielversprechend aussieht, besteht darin, die Verwendung von TCP-Verbindungen auf Port 3306 zu vermeiden und stattdessen Unix-Sockets zu verwenden.

Sie kann Proxy von Port 3306 an die Buchse durch die Portnummer in /etc/mysql/my.cnf ändern und dann socat mit

nohup socat TCP4-LISTEN:3306,fork UNIX-CONNECT:/var/run/mysqld/mysqld.sock& 

Wenn ich mich dann telnet in auf Port 3306 und trennen, kann das Problem nicht provozieren. Ich beabsichtige, darüber zu berichten, wie gut dies im Laufe der Zeit aufgeht.

FWIW, sieht der Code, als ob es das manchmal passieren erwartet:

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

Die socat Workaround, obwohl hässlich, hält gut, also empfehle ich es jedem anderen, der dies trifft. Es sieht so aus, als wäre dies ein Problem, das schon seit einiger Zeit besteht und nur einige Umgebungen betreffen muss (siehe Google und @Roel unten). –

+0

Ein Update. Mit dem socat workaround an der richtigen Stelle sehe ich noch einige Schleifen, die diese Fehler erzeugen, aber sie scheinen schließlich zu enden, und so ist das System weitgehend stabil. –

1

ein wenig Recherchiert und fand folgende;

  1. Präsens in MariaDB auch

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

  2. Percona Server/Percona XtraDB Cluster

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

  3. Alte Fehler von 2010/2012

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

  4. Einige interessante Informationen (sollte nie passieren)

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

[Ich arbeite für Percona]

2

ich das Problem gefunden (oder möglicherweise eines der die Probleme). Hier ist ein Auszug aus strace auf 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! 

In Sperren mein System mit tcp_wrappers ich versehentlich mysqld genommen hatte sowohl aus hosts.allow und hosts.deny. Es scheint, dass nach dem Überprüfen sowohl hosts.allow als auch hosts.deny mysqld den Socket herunterfährt und den Socket wie erwartet schließt. Es beginnt jedoch sofort damit, den (jetzt nicht existierenden) Socket nach Aktivität abzufragen.

Ich habe gerade einen anderen Test, wo meine tcp_wrappers korrekt konfiguriert wurde. Wenn ich von einem autorisierten Host aus eine Verbindung herstelle, ist alles in Ordnung; Wenn ich jedoch von einer blockierten Adresse aus verbunden bin, tritt das gleiche Problem auf. Basierend darauf empfehle ich, andere Tools zu verwenden, um mysqld zu sichern und Ihre tcp_wrappers-Konfiguration offener zu machen als Ihre Firewall. Davon abgesehen sollte der Fehler behoben sein!

Dieser Fix muss noch den Test der Zeit so wie üblich, YMMV bestehen. Hoffe, es hilft sowieso

Nick

+0

Ich hatte genau das gleiche Problem (Protokoll überflutet mit der "Bad File Descriptor" Nachricht und MySQL funktioniert nicht) und suchte viel, bis ich diesen Beitrag gefunden habe. In meinem Fall war es fail2ban, das aus irgendeinem Grund 127.0.0.1 zu /etc/hosts.deny hinzufügte, um das System völlig durcheinander zu bringen! Sobald ich es entfernt habe (und localhost zu /etc/hosts.allow hinzugefügt, um dies in Zukunft zu verhindern), ging es wieder normal. Und die Moral der Geschichte: Als Vorsichtsmaßnahme fügen Sie 127.0.0.1 zu /etc/hosts.allow, nur um sicherzustellen, dass fail2ban nicht in die Quere kommt! –

+0

Ich habe mysqld-Optionen zu hosts.allow und hosts.deny hinzugefügt und sie dann entfernt, als ich feststellte, dass MySQL Workbench nicht ordnungsgemäß verbunden werden konnte. Die Nachrichten, die in der Frage erwähnt werden, überschwemmten meine error.log-Datei, bis ich nicht mehr über Speicherplatz verfügte. Ich habe den mysql-Dienst gestoppt, diese Protokolldatei komprimiert und neu gestartet. Alles scheint jetzt gut. Danke. – user208145