Éliminer les sessions mortes

Yomotsu Hirasaka

      Lors d’une analyse, j’ai constaté que les sessions s’accumulaient au niveau d’un cluster PostgreSQL d’une application originellement développée pour un autre SGBD. Bien trop de sessions par rapport aux utilisateurs et batchs réellement connectés, même en considérant que certains peuvent avoir plusieurs sessions.
      En fait l’application est boguée. Les process clients se terminent quasi TOUJOURS de manière abrupte. Dans ce cas les sessions sont toujours présentes et ne sont éliminées qu’après un délai fixé par défaut au nivau OS (système d’exploitation). Démonstration avec PostgreSQL 9.6 et Debian Stretch :

sysctl -a |grep tcp_keep net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_time = 7200 -- une session cliente set application_name='BOGUEE'; SET -- une session d'administration select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start -------------------------------+------+------------------------------- 2017-05-08 06:15:24.726511+02 | 1640 | 2017-05-08 06:09:57.406011+02 (1 ligne) -- la session cliente meurt abruptement -- dans la session d'administration select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start -------------------------------+------+------------------------------- 2017-05-08 06:18:16.161096+02 | 1640 | 2017-05-08 06:09:57.406011+02 (1 ligne) ... select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start ------------------------------+------+------------------------------- 2017-05-08 08:17:35.20887+02 | 1640 | 2017-05-08 06:09:57.406011+02 (1 ligne) ... select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start ---------------------+-----+--------------- (0 ligne) select statement_timestamp(); statement_timestamp ------------------------------- 2017-05-08 08:22:38.790062+02
Charon, Ankou, Anubis...

      Les sessions mortes abruptement disparaissent de pg_stat_activity au bout d’environ 2 heures. Il faudrait évidemment corriger le bug applicatif. Mais, en attendant, ce délai de 2h est configurable au niveau OS. Démonstration :

-- modification des parametres sysctl -w net.ipv4.tcp_keepalive_intvl = 10 sysctl -w net.ipv4.tcp_keepalive_probes = 6 sysctl -w net.ipv4.tcp_keepalive_time = 600 -- une session cliente set application_name='BOGUEE'; SET -- une session d'administration select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start -------------------------------+------+------------------------------- 2017-05-08 08:38:19.647094+02 | 2116 | 2017-05-08 08:37:31.624305+02 (1 ligne) -- la session cliente meurt abruptement -- dans la session d'administration select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start -------------------------------+------+------------------------------- 2017-05-08 08:39:31.997263+02 | 2116 | 2017-05-08 08:37:31.624305+02 (1 ligne) .. select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start -------------------------------+------+------------------------------- 2017-05-08 08:48:38.306581+02 | 2116 | 2017-05-08 08:37:31.624305+02 (1 ligne) ... select statement_timestamp(), pid, backend_start from pg_stat_activity where application_name = 'BOGUEE'; statement_timestamp | pid | backend_start ---------------------+-----+--------------- (0 ligne) select statement_timestamp(); statement_timestamp ----------------------------- 2017-05-08 08:49:32.6263+02 (1 ligne)

      La session morte passe réellement dans l’autre monde au bout de 10 minutes. Vous pouvez rendre pérennes les changements en renseignant /etc/sysctl.conf par exemple.
      Si vous souhaitez travailler plus finement, il est préférable de positionner les valeurs souhaitées au niveau PostgreSQL (paramètres tcp_keepalives_idle, tcp_keepalives_interval, tcp_keepalives_count) Cependant, de toute façon, PostgreSQL s’appuie sur des mécanismes OS pour cette fonctionnalité. Ne pas réinventer la roue est aussi gage de compacité et d’efficacité.
      Ici, le but était d’éliminer plus rapidement des sessions mortes. Mais un autre intérêt de positionner ces valeurs est bien sûr, à l’inverse, de ne pas voir vos sessions inactives encore vivantes terminées trop vite. Cela peut être le cas s’il existe un firewall entre les clients et le serveur PostgreSQL et s’il est paramétré de manière à tolérer un temps d’inactivité trop faible à votre goût.

Mise à jour : 08/05/2017