Първо нека разберем свойствата на mysql.
interactive_timeout
:интерактивно време за изчакване за сесии на mysql обвивка за секунди като mysqldump или mysql инструменти за команден ред. връзките са в състояние на заспиване. През повечето време това е настроено на по-висока стойност, защото не искате връзката да бъде прекъсната, докато правите нещо на mysql cli.wait_timeout
:количеството секунди по време на неактивност, което MySQL ще изчака, преди да затвори връзка при неинтерактивна връзка за секунди. пример:свързан от java. връзките са в състояние на заспиване.
Сега нека разберем свойствата на c3po и връзката им с DB реквизитите. (Просто ще копирам от вашия въпрос)
Това се отнася до това колко дълго обектът на връзка може да бъде използван и ще бъде наличен в пула. След като времето за изчакване изтече, c3po ще го унищожи или ще го рециклира.
Сега проблемът идва, когато имате maxIdleTime
по-високо от wait_timeout
.да речем, ако mxIdleTime : 50
секунди и wait_timeout : 40 s
тогава има шанс да получите Connection time out exception: Broken Pipe
ако се опитате да извършите някаква операция през последните 10 секунди. Така че maxIdelTime
винаги трябва да е по-малко от wait_timeout
.
Вместо maxIdleTime можете да имате следните свойства.
idleConnectionTestPeriod
задава ограничение за това колко дълго връзката ще остане неактивна, преди да я тества. БезpreferredTestQuery
, по подразбиране еDatabaseMetaData.getTables()
- което не зависи от базата данни и въпреки че е сравнително скъпо обаждане, вероятно е добре за сравнително малка база данни. Ако сте параноични относно производителността, използвайте специфичен за вашата база данни aquery(i.e. preferredTestQuery="SELECT 1")
maxIdleTimeExcessConnections
ще върне обратното възстановяване на connectionCount до minPoolSize след скок в активността.
Моля, имайте предвид, че някое от свойствата на пула (напр. maxIdleTime
) засяга само връзките, които са в пул т.е. ако hibernate е придобил връзка и я държи неактивна повече от maxIdleTime и след това се опита да извърши каквато и да е операция, тогава ще получите „Счупена тръба“
Добре е да имате по-нисък wait_timeout
на mysql, но не винаги е правилно, когато вече имате изградено приложение. Трябва да се уверите, преди да го намалите, че във вашето приложение не поддържате връзката отворена за повече от wait_time
вън.
Също така трябва да имате предвид, че придобиването на връзка е скъпа задача и ако времето за изчакване е твърде малко, тогава това надминава цялата цел на наличието на пул за връзки, тъй като често ще се опитва да придобие връзки.
Това е особено важно, когато не извършвате управление на връзката ръчно, например когато използвате Spring transnational API. Spring стартира транзакция, когато въведете @Transaction
анотиран метод, така че да придобие връзка от пула. Ако извършвате извикване на уеб услуга или четете някакъв файл, което ще отнеме повече време от wait_time out, тогава ще получите изключение.
Сблъсквал съм се с този проблем веднъж.
В един от моите проекти имах cron, който обработваше поръчки за клиенти. За да го направя по-бързо използвах пакетна обработка. Сега, след като извличам партида от клиенти и извършвам някаква обработка (без db повиквания). Когато се опитах да запазя всички поръчки, използвах изключение за счупена тръба. Проблемът беше, че моят wait_timeout беше 1 минута и обработката на поръчката отнемаше повече време от това. Така че трябваше да го увеличим до 2 минути. Можех да намаля размера на партидата, но това правеше цялостната обработка по-бавна.