Ten sam problem miałem w dwóch moich programach. Mój błąd był następujący:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Spędziłem kilka dni, aby rozwiązać ten problem. Przetestowałem wiele podejść, o których wspomniano na różnych stronach internetowych, ale żadne z nich nie zadziałało. W końcu zmieniłem kod i dowiedziałem się, na czym polega problem. Postaram się opowiedzieć o różnych podejściach i podsumować je tutaj .
Kiedy szukałem w Internecie rozwiązania tego błędu, odkryłem, że istnieje wiele rozwiązań, które działały dla co najmniej jednej osoby, ale inni twierdzą, że to nie działa dla nich! dlaczego istnieje wiele sposobów rozwiązania tego błędu? Wygląda na to, że ten błąd może wystąpić ogólnie gdy jest problem z połączeniem z serwerem . Być może problem wynika z nieprawidłowego ciągu zapytania lub zbyt wielu połączeń z bazą danych.
Sugeruję więc wypróbowanie wszystkich rozwiązań jeden po drugim i nie poddawaj się!
Oto rozwiązania, które znalazłem w Internecie i dla każdego z nich jest przynajmniej osoba, której problem został rozwiązany za pomocą tego rozwiązania.
Wskazówka:rozwiązania, których potrzebujesz, aby zmienić ustawienia MySQL, możesz znaleźć w następujących plikach:
-
Linux:
/etc/mysql/my.cnf
lub/etc/my.cnf
(w zależności od używanej dystrybucji Linuksa i pakietu MySQL) -
Windows:
C:\**ProgramData**\MySQL\MySQL Server 5.6\my.ini
(Zauważ, że to ProgramData, a nie Program Files)
Oto rozwiązania:
-
zmiana
bind-address
atrybut:Usuń komentarz
bind-address
atrybut lub zmień go na jeden z następujących adresów IP:bind-address="127.0.0.1"
lub
bind-address="0.0.0.0"
-
komentowanie „pomijania sieci”
Jeśli istnieje
skip-networking
w pliku konfiguracyjnym MySQL, skomentuj, dodając#
znak na początku tej linii. -
zmień „wait_timeout” i „interactive_timeout”
Dodaj te wiersze do pliku konfiguracyjnego MySQL:
[wait_timeout][1] = *number* interactive_timeout = *number* connect_timeout = *number*
-
Upewnij się, że Java nie tłumaczy „localhost” na [:::1] zamiast [127.0.0.1]
Ponieważ MySQL rozpoznaje
127.0.0.1
(IPv4
) ale nie:::1
(IPv6
)Można tego uniknąć, stosując jedno z dwóch podejść:
-
W ciągu połączenia użyj
127.0.0.1
zamiastlocalhost
aby uniknąćlocalhost
tłumaczone na:::1
-
Uruchom java z opcją
-Djava.net.preferIPv4Stack=true
aby zmusić java do używaniaIPv4
zamiastIPv6
. W systemie Linux można to również osiągnąć, uruchamiając (lub umieszczając go w/etc/profile
:export _JAVA_OPTIONS="-Djava.net.preferIPv4Stack=true"
-
-
sprawdź ustawienia proxy systemu operacyjnego, zapory sieciowe i programy antywirusowe
Upewnij się, że zapora lub oprogramowanie antywirusowe nie blokuje usługi MySQL.
Zatrzymaj tymczasowo iptables na Linuksie. Jeśli iptables są źle skonfigurowane, mogą zezwalać na wysyłanie pakietów tcp do portu mysql, ale blokują powrót pakietów tcp na tym samym połączeniu.
# Redhat enterprise and CentOS systemctl stop iptables.service # Other linux distros service iptables stop
Zatrzymaj oprogramowanie antywirusowe w systemie Windows.
-
zmień parametry połączenia
Sprawdź ciąg zapytania. twoje parametry połączenia powinny wyglądać mniej więcej tak:
dbName = "my_database"; dbUserName = "root"; dbPassword = ""; String connectionString = "jdbc:mysql://localhost/" + dbName + "?user=" + dbUserName + "&password=" + dbPassword + "&useUnicode=true&characterEncoding=UTF-8";
Upewnij się, że w ciągu nie ma spacji. Cały ciąg połączenia powinien być kontynuowany bez żadnych znaków spacji.
Spróbuj zastąpić „localhost” adresem sprzężenia zwrotnego 127.0.0.1. Spróbuj także dodać numer portu do ciągu połączenia, na przykład:
String connectionString = "jdbc:mysql://localhost:3306/my_database?user=root&password=Pass&useUnicode=true&characterEncoding=UTF-8";
Zazwyczaj domyślny port dla MySQL to 3306.
Nie zapomnij zmienić nazwy użytkownika i hasła na nazwę użytkownika i hasło do serwera MySQL.
- zaktualizuj plik biblioteki sterownika JDK
- przetestuj różne JDK i JRE (takie jak JDK 6 i 7)
- nie zmieniaj max_allowed_packet
„max_allowed_packet " to zmienna w pliku konfiguracyjnym MySQL, która wskazuje maksymalny rozmiar pakietu, a nie maksymalną liczbę pakietów. Nie pomoże więc rozwiązać tego błędu.
- zmień zabezpieczenia tomcat
zmień TOMCAT6_SECURITY=tak na TOMCAT6_SECURITY=nie
- użyj właściwości validationQuery
użyj validationQuery="select now()", aby upewnić się, że każde zapytanie ma odpowiedzi
- Automatyczne ponowne łączenie
Dodaj ten kod do ciągu połączenia:
&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
Chociaż żadne z tych rozwiązań nie zadziałało dla mnie, proponuję je wypróbować. Ponieważ są ludzie, którzy rozwiązali swój problem, wykonując te kroki.
Ale co rozwiązało mój problem?
Mój problem polegał na tym, że miałem wiele SELECTów w bazie danych. Za każdym razem tworzyłem połączenie, a następnie je zamykałem. Co prawda za każdym razem zamykałem połączenie, ale system napotkał wiele połączeń i dał mi ten błąd. Zrobiłem to, że zdefiniowałem swoją zmienną połączenia jako publiczną (lub prywatną) zmienną dla całej klasy i zainicjowałem ją w konstruktorze. Potem za każdym razem, gdy po prostu korzystałem z tego połączenia. To rozwiązało mój problem, a także znacznie zwiększyło moją prędkość.
#Wniosek#Nie ma prostego i unikalnego sposobu na rozwiązanie tego problemu. Proponuję zastanowić się nad własną sytuacją i wybrać powyższe rozwiązania. Jeśli weźmiesz ten błąd na początku programu i nie możesz w ogóle połączyć się z bazą danych, możesz mieć problem z ciągiem połączenia. Ale jeśli popełnisz ten błąd po kilku udanych interakcjach z bazą danych, problem może dotyczyć liczby połączeń i możesz pomyśleć o zmianie „wait_timeout” i innych ustawieniach MySQL lub przepisać kod w taki sposób, aby zmniejszyć liczbę połączeń.