Image de couverture : Collations PostgreSQL : comment une mise à jour glibc peut corrompre vos index en silence
tech

Collations PostgreSQL : comment une mise à jour glibc peut corrompre vos index en silence

08 April 2026
6 min de lecture
4 vues
Sébastien Muler

Collations PostgreSQL : comment une mise à jour glibc peut corrompre vos index en silence

En août 2018, la GNU C Library (glibc) publiait sa version 2.28. Un changement en apparence banal, mais qui a déclenché l'un des incidents de corruption de données les plus insidieux de l'histoire de PostgreSQL. Des index silencieusement invalides, des résultats de requêtes qui changent sans prévenir, des contraintes UNIQUE qui ne tiennent plus — et Postgres qui ne se plaint pas. Voici ce que tout développeur PHP/Symfony hébergeant PostgreSQL doit savoir, et la checklist opérationnelle pour s'en prémunir.

📖 Cet article s'appuie sur l'analyse approfondie de Shaun Thomas publiée sur le blog pgEdge.


Qu'est-ce qu'une collation, et pourquoi ça casse tout ?

Une collation définit les règles de comparaison et de tri du texte. En anglais basique, ça semble trivial. Mais dès qu'on sort de l'alphabet ASCII, les choses se compliquent : est-ce que ß est équivalent à ss ? Est-ce que é et è se trient comme des variantes de e ? En suédois, ä et ö se placent après z — pas comme des variantes de a et o.

PostgreSQL délègue ces règles à la bibliothèque système (glibc sur Linux, ou ICU si configuré explicitement). C'est là que réside le problème : quand glibc change ses règles de tri, l'ordre de vos index change aussi — mais les index existants, eux, ne sont pas reconstruits automatiquement.

La version 2.28 de glibc a intégré 18 ans de modifications accumulées sur les locales, alignées sur la norme ISO 14651 Édition 4 et Unicode 9.0.0. Résultat : des milliers de bases de données PostgreSQL dans le monde se sont retrouvées avec des index dont l'ordre interne ne correspondait plus aux règles de tri effectives. Requêtes qui retournent des résultats incomplets, contraintes d'unicité contournées, comportements non déterministes — le tout sans la moindre erreur dans les logs.


🔍 Checklist : détecter une corruption liée aux collations

Avant toute intervention, il faut savoir si votre base est affectée.

1. Identifier la version de glibc sur votre système

ldd --version
# ou
/lib/x86_64-linux-gnu/libc.so.6 --version

Si vous êtes sur glibc >= 2.28, vous êtes dans la zone à risque si vos bases ont été créées ou migrées depuis une version antérieure.

2. Vérifier la collation utilisée par vos bases

SELECT datname, datcollate, datctype
FROM pg_database;

Une base en fr_FR.UTF-8 ou en_US.UTF-8 utilise glibc. Une base en und-x-icu ou toute collation préfixée pg_catalog. avec provider = 'icu' est isolée du problème.

3. Détecter les index potentiellement corrompus

PostgreSQL >= 14 intègre la fonction pg_check_relation_size(), mais pour les collations, l'outil le plus direct est amcheck :

CREATE EXTENSION IF NOT EXISTS amcheck;

SELECT bt_index_check(oid, true)
FROM pg_class
WHERE relkind = 'i'
  AND relname NOT LIKE 'pg_%';

Toute erreur levée ici indique un index dont l'ordre interne est incohérent — corruption confirmée.

4. Vérifier la version de collation enregistrée

SELECT collname, collversion, pg_collation_actual_version(oid)
FROM pg_collation
WHERE collprovider = 'c';

Une divergence entre collversion et pg_collation_actual_version() signale que la bibliothèque système a changé depuis la création de la base.


🔧 Réparer : REINDEX ou dump+restore ?

Deux stratégies selon la criticité et la taille de vos données.

Option 1 — REINDEX (rapide, en place)

-- Sur une table spécifique
REINDEX TABLE CONCURRENTLY ma_table;

-- Sur toute la base (PostgreSQL 12+)
REINDEX DATABASE CONCURRENTLY ma_base;

L'option CONCURRENTLY reconstruit les index sans poser de verrou exclusif — indispensable en production. À l'issue, mettez à jour la version de collation enregistrée :

ALTER COLLATION "fr-FR-x-icu" REFRESH VERSION;

Option 2 — Dump + restore (recommandé pour une migration propre)

Si vous en profitez pour migrer vers ICU (la bonne décision long terme) :

pg_dump -Fc ma_base > ma_base.dump

# Recréer la base avec ICU
createdb --locale=und-x-icu --lc-collate=und-x-icu --lc-ctype=und-x-icu -T template0 ma_base_icu

pg_restore -d ma_base_icu ma_base.dump

ICU (International Components for Unicode) est une bibliothèque indépendante de glibc, versionnable et stable entre OS. C'est la recommandation officielle de la communauté PostgreSQL pour toute nouvelle installation.


🐳 Docker : pinner vos images pour éviter les surprises glibc

Dans un contexte Docker, le problème est amplifié : une simple mise à jour d'image peut faire passer votre conteneur PostgreSQL de glibc 2.27 à 2.28+, corrompant silencieusement vos index au premier redémarrage.

Règle absolue : ne jamais utiliser le tag latest ou un tag mineur flottant.

# ❌ Dangereux
image: postgres:16

# ✅ Reproductible
image: postgres:16.3-bookworm

Et pour vos pipelines CI, ajoutez systématiquement une vérification post-migration :

# Dans votre CI (GitHub Actions, GitLab CI...)
- name: Vérifier l'intégrité des index PostgreSQL
  run: |
    psql $DATABASE_URL -c "
      CREATE EXTENSION IF NOT EXISTS amcheck;
      SELECT bt_index_check(oid, true)
      FROM pg_class
      WHERE relkind = 'i' AND relname NOT LIKE 'pg_%';
    "

Ce check doit faire partie de votre suite de tests de migration, au même titre que les assertions fonctionnelles sur vos données.


Conclusion : migrez vers ICU, maintenant

La corruption de collation glibc n'est pas un bug exotique réservé aux edge cases — c'est un risque réel pour toute base PostgreSQL hébergée sur Linux avec une locale non-ASCII et une histoire de mises à jour OS. La bonne nouvelle : la solution existe, elle est documentée, et elle est définitive.

Plan d'action MulerTech :

  1. Auditer toutes les bases (glibc vs ICU) avec les requêtes ci-dessus
  2. Lancer amcheck sur les bases à risque
  3. Planifier un dump+restore vers ICU sur les bases critiques
  4. Pinner les images Docker PostgreSQL sur des tags immutables
  5. Intégrer le check amcheck dans les pipelines CI

Le vrai danger avec ce type de corruption, c'est qu'on ne la voit pas venir. Mieux vaut passer une après-midi à auditer que de découvrir des données incohérentes en production un vendredi soir.

Partager cet article