OOM Killer

Quand Thanatos tue Hypnos...

      Dans cet article sur le traqueur, nous avions observé que le cluster PostgreSQL plantait complètement suite à l’optimisation ratée d’un traitement. Linux dispose d’un mécanisme permettant d’éviter le crash complet du serveur si la mémoire vient à manquer. Un mécanisme, OOM Killer, fait le ménage, tue des process et libère des ressources. Le problème est que ce tueur peut s’en prendre au process principal de PostgreSQL et provoquer un plantage généralisé.
      Démonstration avec Debian Stretch et PostgreSQL 9.6 :

cat /etc/*se PRETTY_NAME="Debian GNU/Linux 9 (stretch)" NAME="Debian GNU/Linux" VERSION_ID="9" VERSION="9 (stretch)" ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" select version(); version --------------------------------------------------------------------------------------------------- PostgreSQL 9.6.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-10) 6.3.0 20170321, 64-bit (1 ligne) create table t1(c1 timestamp, c2 smallint, c3 smallint, c4 smallint); CREATE TABLE start transaction; START TRANSACTION -- 10 millions de valeurs en une seule instruction INSERT VALUES insert into t1 values (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), ... (current_timestamp , 100, 100, 100) ; la connexion au serveur a été coupée de façon inattendue Le serveur s’est peut-être arrêté anormalement avant ou durant le traitement de la requête. la connexion au serveur a été perdue -- dans une autre session select pg_sleep(3600); ATTENTION: arrêt de la connexion à cause de l’arrêt brutal d’un autre processus serveur DÉTAIL : Le postmaster a commandé à ce processus serveur d’annuler la transaction courante et de quitter car un autre processus serveur a quitté anormalement et qu’il existe probablement de la mémoire partagée corrompue. ASTUCE : Dans un moment, vous devriez être capable de vous reconnecter à la base de données et de relancer votre commande. la connexion au serveur a été coupée de façon inattendue Le serveur s’est peut-être arrêté anormalement avant ou durant le traitement de la requête. La connexion au serveur a été perdue. Tentative de réinitialisation : Échec. grep oom-killer /var/log/messages Apr 29 14:49:51 srvdeb96 kernel: [ 3158.162183] postgres invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0

Protection contre la mort, abjuration, niveau 4

      Le process de la session folle a été tué mais notre session qui dormait tranquillement a été terminée également. En fait, tout le serveur PostgreSQL est tombé !
      La documentation PostgreSQL explique comment modifier la configuration de Linux pour limiter ce comportement. Il s’agit d’être plus conservateur dans l’allocation de la mémoire. Démonstration :

sysctl -w vm.overcommit_memory=2 vm.overcommit_memory = 2 sysctl -w vm.overcommit_ratio=90 vm.overcommit_ratio = 90 -- traitement fou start transaction; START TRANSACTION insert into t1 values (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), (current_timestamp , 100, 100, 100), ... (current_timestamp , 100, 100, 100) ; ERROR: out of memory DÉTAIL : Failed on request of size 262144. ROLLBACK -- autre session select pg_sleep(3600);


      Le process fou n’a pas obtenu la mémoire qu’il demandait et la transaction a été annulée. Le process qui dormait tranquillement n’a cette fois rien remarqué et, de manière générale, le serveur PostgreSQL n’est pas tombé. Vous pouvez si vous le souhaitez rendre permanente cette configuration en renseignant /etc/sysctl.conf par exemple.
      Positionner vm.overcommit_memory=2 et vm.overcommit_ratio=90 signifie qu’il n’est pas possible de surallouer de la mémoire, en l’occurence d’allouer plus de SWAP + (RAM X 0,9). Le paramétrage par défaut de Linux n’est cependant pas à remettre en cause, il convient dans la plupart des cas. Cette précaution n’est utile que si tous les process du serveur ne sont pas sous contrôle, ce qui peut être le cas sur un serveur hybride transactionnel et décisionnel. PostgreSQL propose toutefois d’autres options dans ce cas, notamment reporter la charger décisionnelle sur une Hot Standby, une base de secours en réplication ET en lecture seule. Cette fonctionnalité est équivalente à l’option Active Dataguard d’Oracle Database Enterprise Edition.

Mise à jour : 29/04/2017