HikariCP: какие тайм-ауты на уровне базы данных следует учитывать для установки maxLifetime для Oracle 11g

В документации к HikariCP упоминается, что

Мы настоятельно рекомендуем установить это значение, и оно должно быть как минимум на 30 секунд меньше любого времени ожидания соединения на уровне базы данных.

Какие тайм-ауты подключения на уровне базы данных следует учитывать для базы данных Oracle11.2? И как я мог найти эти тайм-ауты (запросы на выполнение)?


person NaveenBabuE    schedule 30.09.2016    source источник


Ответы (1)


Краткий ответ: нет (по умолчанию).


Для справки (чтобы включить сюда подробности на случай изменения ссылки), мы говорим о свойстве maxLifetime HikariCP:

Это свойство управляет максимальным временем жизни соединения в пуле. Используемое соединение никогда не будет удалено, только когда оно будет закрыто, оно будет удалено. Настоятельно рекомендуется установить это значение, и оно должно быть как минимум на 30 секунд меньше, чем любая база данных или инфраструктура, ограничивающая время подключения. Значение 0 указывает на отсутствие максимального времени жизни (бесконечное время жизни), при условии, конечно, параметр idleTimeout. По умолчанию: 1800000 (30 минут)

По моему опыту, хорошо, что HikariCP это делает. Насколько я могу судить, по умолчанию Oracle не устанавливает максимальное время жизни для соединений (ни на стороне драйвера JDBC (1), ни на стороне сервера (2)). Таким образом, в этом отношении "ограничение времени соединения, налагаемое инфраструктурой" равно +бесконечности, и это было проблемой для нас, поскольку мы наблюдали проблемы с долгоживущими соединениями. Это также означает, что любое значение "минимум на 30 секунд меньше", включая значение по умолчанию :)

Я предполагаю, что уровень подключения ничего не делает по этому поводу, потому что он рассчитывает на уровень пула выше, чтобы справиться с такими вещами. Это было невозможно с (теперь устаревшим) неявным пулом соединений, и я не знаю, является ли UCP (замена) делает это, но если вы используете HikariCP, вы их не используете.

Теперь, через 30 минут (обычно после многих повторных использований в разных целях) для заданного соединения HikariCP закрывает его и создает новое. Это имеет очень небольшую стоимость и устранило наши проблемы с долгоживущими соединениями. Мы довольны этим значением по умолчанию, но на всякий случай делаем его настраиваемым (см. 2 ниже).

(1) OracleDataSource не предлагает никаких точка конфигурации (свойство или системное свойство) для управления этим, и я наблюдал бесконечное время жизни.

(2) Ограничения на стороне сервера см. в параметре профиля IDLE_TIME. . Цитируя этот ответ:

Oracle по умолчанию не закрывает соединение из-за бездействия. Вы можете настроить профиль с IDLE_TIME, чтобы заставить Oracle закрывать неактивные соединения.

Чтобы проверить, каково значение IDLE_TIME для вашего пользователя, объединив ответы из этих вопросов и ответов:

select p.limit
from dba_profiles p, dba_users u
where p.resource_name = 'IDLE_TIME' and p.profile = u.profile and u.username = '...'
;

Значение по умолчанию: UNLIMITED.

Обратите внимание, что в другом месте могут быть установлены другие ограничения (брандмауэр... да, я был укушен этим, хотя в большинстве систем БД есть механизм проверки активности), которые могут мешать. Так что лучше сделать его настраиваемым на случай, если такие проблемы обнаружатся при развертывании вашего продукта.


В Linux вы можете проверить максимальное время жизни физических подключений, отслеживая TCP-сокеты, подключенные к вашей базе данных. Я запускал приведенный ниже скрипт на своем сервере (с точки зрения БД, который является хостом client), он принимает 1 аргумент, ip:port вашего узла оракула, как показано в выводе netstat -tan ( или шаблон, если у вас несколько узлов).

#!/bin/bash
target="$1"
dir=$(mktemp -d)
while sleep 10
do
    echo "------------ "$(date)
    now=$(date +%s)
    netstat -tan | grep " $target " | awk '{print $4}' | cut -f2 -d: | while read port
    do
        file="p_$port"
        [ ! -e $file ] && touch $file
        ftime=$(stat -c %Z "$file")
        echo -e "$port :\t "$(( now - ftime))
    done
done
\rm "$dir"/p_*
\rmdir "$dir"

Если вы запустите это и остановите его с помощью Ctrl-C в течение sleep времени, он должен выйти из цикла и очистить временный каталог, но это не на 100% надежно

В результатах ни один из портов не должен показывать значение, превышающее 1800 секунд (т.е. 30 минут), плюс-минус минута. См. пример вывода ниже, первый пример показывает 2 сокета выше 1800, они исчезли через 10 секунд.

------------ Thu Jul 6 16:09:00 CEST 2017
49806 :  1197
49701 :  1569
49772 :  1348
49782 :  1317
49897 :  835
49731 :  1448
49620 :  1830
49700 :  1569
49986 :  523
49722 :  1498
49715 :  1509
49711 :  1539
49629 :  1820
49732 :  1448
50026 :  332
49849 :  1036
49858 :  1016
------------ Thu Jul 6 16:09:10 CEST 2017
49806 :  1207
49701 :  1579
49772 :  1358
49782 :  1327
49897 :  845
49731 :  1458
49700 :  1579
49986 :  533
49722 :  1508
49715 :  1519
49711 :  1549
49732 :  1458
50026 :  342
49849 :  1046
49858 :  1026

Чтобы убедиться в этом, вам потребуется запустить скрипт более чем на 30 минут, потому что он не знает возраста сокетов, существовавших ранее

person Hugues M.    schedule 05.07.2017
comment
А, хороший вопрос! На моем сервере есть Groovy Shell (очень похожая на Jenkins Script Console), который я использовал для проверки объектов подключения во время выполнения. И я мог убедиться, что по истечении срока Хикари закроет их и создаст новые. Я не на работе, поэтому я не могу показать, как именно сейчас (может попробовать позже, если нужно), но это была идея. Вы также можете использовать netstat для проверки открытых TCP-сокетов, подключенных к вашей БД, принять к сведению пары номеров портов и убедиться, что ни один сокет не выживает в течение 30 минут. - person Hugues M.; 06.07.2017
comment
Я добавил рецепт, чтобы проверить это в Linux (надеюсь, вы используете Linux... на Mac он также должен работать с минимальными изменениями) - person Hugues M.; 06.07.2017