Najpierw zrozummy właściwości mysql.
interactive_timeout
:interaktywny limit czasu dla sesji powłoki mysql w ciągu kilku sekund, takich jak mysqldump lub narzędzia wiersza poleceń mysql. połączenia są w stanie uśpienia. W większości przypadków jest to ustawione na wyższą wartość, ponieważ nie chcesz, aby było rozłączane, gdy robisz coś na mysql cli.wait_timeout
:ilość sekund podczas braku aktywności, które MySQL będzie czekał, zanim zamknie połączenie na nieinteraktywnym połączeniu w ciągu sekund. przykład:podłączony z javy. połączenia są w stanie uśpienia.
Teraz zrozummy właściwości c3po i ich związek z właściwościami DB. (Po prostu skopiuję z twojego pytania)
Odnosi się to do tego, jak długo obiekt połączenia może być używany i będzie dostępny w puli. Po upływie limitu czasu c3po zniszczy go lub podda recyklingowi.
Teraz problem pojawia się, gdy masz maxIdleTime
wyższy niż wait_timeout
.powiedzmy, że mxIdleTime : 50
s i wait_timeout : 40 s
wtedy jest szansa, że otrzymasz Connection time out exception: Broken Pipe
jeśli spróbujesz wykonać jakąkolwiek operację w ciągu ostatnich 10 sekund. Więc maxIdelTime
powinna zawsze być mniejsza niż wait_timeout
.
Zamiast maxIdleTime możesz skorzystać z następujących właściwości.
idleConnectionTestPeriod
ustala limit czasu, przez jaki połączenie pozostanie bezczynne przed jego przetestowaniem. BezpreferredTestQuery
, wartość domyślna toDatabaseMetaData.getTables()
- co jest niezależne od bazy danych i chociaż stosunkowo drogie wywołanie, prawdopodobnie jest dobre dla stosunkowo małej bazy danych. Jeśli masz paranoję na punkcie wydajności, użyj zapytania specyficznego dla Twojej bazy danych(i.e. preferredTestQuery="SELECT 1")
maxIdleTimeExcessConnections
przywróci backdown connectionCount do minPoolSize po wzroście aktywności.
Należy pamiętać, że dowolna właściwość puli (np. maxIdleTime
) wpływa tylko na połączenia, które są w puli np. jeśli hibernacja nawiązała połączenie i utrzymuje je w stanie bezczynności przez okres maxIdleTime, a następnie spróbuje wykonać jakąkolwiek operację, otrzymasz komunikat „Broken Pipe”
Dobrze jest mieć niższy wait_timeout
na mysql, ale nie zawsze jest dobrze, gdy masz już zbudowaną aplikację. Musisz upewnić się przed zmniejszeniem, że w swojej aplikacji nie utrzymujesz otwartego połączenia dłużej niż wait_time
na zewnątrz.
Musisz również wziąć pod uwagę, że nabycie połączenia jest kosztownym zadaniem, a jeśli czas oczekiwania jest zbyt krótki, to bije cały cel posiadania puli połączeń, ponieważ często będzie próbował uzyskać połączenia.
Jest to szczególnie ważne, gdy nie zarządzasz połączeniami ręcznie, na przykład podczas korzystania z transnarodowego API Spring. Spring rozpoczyna transakcję, gdy wpiszesz @Transaction
z adnotacjami, dzięki czemu uzyskuje połączenie z puli. Jeśli wykonujesz jakiekolwiek wywołanie usługi sieciowej lub czytasz jakiś plik, który zajmie więcej czasu niż wait_time out, otrzymasz wyjątek.
Już raz spotkałem się z tym problemem.
W jednym z moich projektów miałem crona, który realizował zamówienia dla klientów. Aby przyspieszyć, wykorzystałem przetwarzanie wsadowe. Teraz raz pobrać partię klientów i wykonać pewne przetwarzanie (bez wywołań db). Kiedy próbuję zapisać wszystkie zamówienia, otrzymuję wyjątek zepsutej rury. Problem polegał na tym, że mój wait_timeout wynosił 1 minutę, a przetwarzanie zamówienia zajmowało więcej czasu. Musieliśmy więc zwiększyć go do 2 minut. Mogłem zmniejszyć rozmiar partii, ale to spowodowało spowolnienie całego przetwarzania.