2016-06-13 13 views
5

Niedawno zaktualizowany do MySQL 5.7.12 na Debianie (Debian 3.2.78-1 x86_64 GNU/Linux) i był uruchomiony na serwerze zawieszonym co kilka godzin . To jest coraz zalane w syslog i mysql.log:MySQL - 0 [ERROR] Błąd akceptacji: Niepoprawny deskryptor pliku

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

informacji MySQL: mysql Ver 14.14 Distrib 5.7.12-5, na debian-linux-gnu (x86_64), stosując 6,2

kawałki my.cnfmysqld sekcji, które mogą kierować jakąś pomoc o wartości szczypanie:

[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 

Odpowiedz

1

Mieliśmy ten sam problem w systemie Ubuntu 16.04 z mysql 5.7.13. Zwiększyliśmy maksymalną otwartą parametr pliki w Systemd tak:

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

[Service] 
LimitNOFILE=1000000 

tej pory problem nie stało jeszcze raz. Może mysql potrzebuje teraz więcej deskryptorów plików.

+0

Tylko heads-rynki stanowiące W moim systemie FC24 podczas aktualizowania MariaDB z DNF, plik został nadpisany Systemd i ten problem powtarzały. – glyph

+0

Niestety ta poprawka nie działa tutaj. Napotkano ten błąd na nowych instancjach Ubuntu 16.04 i Ubuntu 16.10 z MySQL 5.7.17. (BTW Myślę, że należy najpierw utworzyć folder mysql.service i uruchomić 'systemctl daemon-reload'). – mahemoff

0

Mam taki sam problem po aktualizacji do klastra Percona 5.7.14-26.17-1.trusty.

Sugestia ulimit.conf nie pomaga i upewniłem się, że istnieje wystarczająca liczba uchwytów plików, o ile mogę to stwierdzić, edytując /etc/security/limits.conf i/etc/sysctl. conf.

Mogę to odtworzyć łatwo przez telnetowanie do postu 3306, a następnie rozłączanie; serwer następnie przechodzi do wirowania rejestrując ten błąd.

Okropnym rozwiązaniem tego problemu, który wygląda obiecująco w moim środowisku, jest unikanie używania połączeń TCP na porcie 3306 i używanie zamiast nich gniazd unixowych.

Można proxy z portu 3306 do gniazda poprzez zmianę numeru portu w pliku /etc/mysql/my.cnf a następnie za pomocą socat

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

Gdybym wtedy telnet na port 3306 i rozłączeniem, ja nie może sprowokować problemu. Zamierzam złożyć raport na temat tego, jak dobrze to się zmienia.

FWIW, kod wygląda tak, jakby to oczekuje się zdarzyć czasami:

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

Obciążenie obejściem społeczności, choć brzydkie, dobrze się układa, więc polecam go każdemu, kto to uderzy. Wygląda na to, że jest to problem występujący od jakiegoś czasu i może dotyczyć tylko niektórych środowisk (zobacz poniżej Google i @Roel). –

+0

Aktualizacja. W przypadku obejścia problemu przez społeczność nadal widzę niektóre pętle powodujące te błędy, ale ostatecznie wydają się one kończyć, a więc system jest zasadniczo stabilny. –

1

Zbadał trochę i znalazłem następujący;

  1. Obecne w MariaDB również

    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. Old bug z 2010/2012

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

  4. kilka ciekawych informacji (nigdy nie powinno się zdarzyć)

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

[pracuję Percona]

2

znalazłem problem (lub ewentualnie jeden z problemy). Oto wyciąg z strace na 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! 

W blokowania mój system z tcp_wrappers ja przypadkowo podjętych mysqld z obu hosts.allow i hosts.deny. Wydaje się, że po sprawdzeniu zarówno hosts.allow, jak i hosts.deny mysqld zamyka się i zamyka gniazdo tak, jak można się spodziewać. Jednak natychmiast zaczyna odpytywać (nieistniejące) gniazdo aktywności.

Właśnie zrobiłem kolejny test, w którym moje tcp_wrappers zostało poprawnie skonfigurowane. Kiedy łączę się z autoryzowanym hostem, wszystko jest w porządku; jednak gdy połączyłem się z zablokowanego adresu, pojawia się ten sam problem. Na tej podstawie zalecam używanie innych narzędzi, aby zabezpieczyć mysqld i uczynić twoją konfigurację tcp_wrappers bardziej otwartą niż twoja zapora ogniowa. Mimo to błąd powinien zostać naprawiony!

Ta poprawka musi jeszcze wytrzymać próbę czasu, tak jak zwykle, YMMV. Nadzieję, że to pomaga i tak

Nick

+0

Miałem dokładnie ten sam problem (log został zalany z komunikatem "zły deskryptor pliku", a MySQL nie działał) i dużo przeszukano, dopóki nie znalazłem tego wpisu. W moim przypadku był to błąd2ban, który z jakiegoś powodu dodał 127.0.0.1 do /etc/hosts.deny, aby całkowicie zepsuć system! Po usunięciu (i dodaniu lokalnego hosta do /etc/hosts.allow, aby zapobiec temu w przyszłości), wszystko wróciło do normy. I morale historii: jako środek ostrożności dodaj 127.0.0.1 do /etc/hosts.allow, aby upewnić się, że fail2ban nie wchodzi ci w drogę! –

+0

Dodałem kilka opcji mysqld do hosts.allow i hosts.deny, a następnie usunąłem je, gdy stwierdziłem, że MySQL Workbench nie połączy się poprawnie. Wiadomości wymienione w pytaniu zalały mój plik error.log, dopóki nie zabrakło miejsca na dysku. Zatrzymałem usługę mysql, skompresowałem ten plik dziennika i zrestartowałem. Wszystko wydaje się teraz dobrze. Dzięki. – user208145

Powiązane problemy