Sujet : databases
-
Rendre visibles les limites des transactions
Documenter quels changements d'état sont validés (commit) ensemble, et ce qui peut se produire entre les transactions de base de données et les appels externes.
-
Recherche plein texte dans PostgreSQL avec tsvector
PostgreSQL transforme le texte en un tsvector de lexèmes normalisés selon une configuration linguistique, le confronte à un tsquery, classe les correspondances avec ts_rank et l'indexe avec GIN ; il gère la racinisation et les mots vides, mais pas les fautes de frappe ni les synonymes sans configuration supplémentaire.
-
Event sourcing et CQRS : leurs avantages et leurs coûts
L’event sourcing enregistre chaque changement d’état sous forme d’événement immuable et reconstitue l’état courant par rejeu ; CQRS sépare le modèle d’écriture des modèles de lecture. Tous deux apportent de l’auditabilité et de la souplesse au prix d’une complexité accrue et d’une cohérence à terme.
-
Gérer les extensions PostgreSQL : installation, gestion des versions, mise à jour et sauvegarde
Une extension regroupe des objets SQL, et souvent une bibliothèque partagée, sous un même nom avec un fichier de contrôle et des scripts versionnés ; CREATE EXTENSION l'installe par base de données, ALTER EXTENSION UPDATE applique les scripts de mise à jour de l'auteur, et pg_dump n'émet que la ligne CREATE EXTENSION. Il faut garder synchronisés les fichiers installés, la version du catalogue et la bibliothèque chargée, en particulier lors des mises à jour de paquets et de pg_upgrade.
-
Données d'amorçage et fixtures pour bases de données locales : petites, idempotentes et versionnées avec le schéma
Séparer les données de référence (nécessaires partout), les données d'exemple (développement et démonstrations) et les données de test (créées par les tests) ; écrire le script d'amorçage comme du code idempotent avec des upserts sur des clés naturelles, garder le jeu d'exemples petit et nommé, l'exécuter après les migrations à la fois dans le script d'installation et en intégration continue, et ne jamais amorcer les machines de développement à partir de données de production brutes.
-
Concevoir une table de séries temporelles en ajout seul dans PostgreSQL
Stocker les mesures dans une table partitionnée par plage temporelle avec timestamptz, une clé composite de série et de temps, des index adaptés au schéma de requête (B-tree par série, BRIN pour les scans temporels sur toute la table) et une rétention mise en œuvre en détachant puis en supprimant des partitions plutôt qu'avec DELETE ; ces choix découlent du fait que les lignes arrivent dans l'ordre chronologique et repartent par tranches temporelles entières.
-
Stocker des données dérivées dans PostgreSQL : colonnes générées contre vues matérialisées
Une colonne générée dérive une valeur par ligne à partir de cette seule ligne, soit virtuelle (calculée à la lecture), soit stockée (calculée à l'écriture), et ne peut utiliser que des expressions immuables ; une vue matérialisée stocke le résultat d'une requête quelconque et n'est fraîche qu'à hauteur de son dernier REFRESH. Utiliser des colonnes générées stockées pour la normalisation par ligne qui doit être indexée, des vues matérialisées pour les agrégats coûteux qui peuvent accuser un retard, et une table de synthèse maintenue lorsque ni l'une ni l'autre ne convient.
-
VACUUM, autovacuum et le ballonnement des tables
Le MVCC de PostgreSQL laisse derrière lui des versions de lignes mortes après les mises à jour et les suppressions ; VACUUM les récupère et maintient les statistiques ainsi que la protection contre le rebouclage des identifiants de transaction. Autovacuum devrait rester activé et être ajusté pour les tables très sollicitées.
-
Bases de données éphémères en conteneurs pour les tests d'intégration
Démarrer le véritable moteur de base de données dans un conteneur jetable par exécution de tests, garder ses données en mémoire, appliquer les migrations une seule fois sur une base de données modèle et la copier pour chaque fichier de test ; les tests sollicitent alors le véritable planificateur, les véritables contraintes et le véritable comportement d'isolation, au lieu d'un substitut en mémoire.
-
Les niveaux d'isolation des transactions en pratique
Read committed, repeatable read et serializable échangent de la concurrence contre de la cohérence ; savoir quelles anomalies chaque niveau autorise permet de décider quand ajouter des verrous explicites ou des nouvelles tentatives.
-
Modifications de base de données sans interruption de service : expand et contract
Modifier un schéma en trois étapes livrables séparément : étendre (créer une nouvelle colonne ou table, conserver l'ancienne), migrer (écrire en double et rattraper par lots), puis réduire (supprimer l'ancien dès que tout le code utilise le nouveau) ; éviter les verrous longs en ne réécrivant jamais une table entière dans une seule instruction, et en limitant chaque attente avec lock_timeout.
-
Données de test sans données personnelles issues de la production
Donner à un environnement de développement, à la CI et à la préproduction des données réalistes en les générant : classer les colonnes, écrire des générateurs à graine fixe qui passent les validateurs de l'application, produire du volume avec generate_series, ne copier que des distributions depuis la production, marquer les enregistrements générés de façon reconnaissable, et supprimer le raccourci consistant à copier la production.
-
NULL en SQL : logique à trois valeurs et ses pièges
NULL signifie inconnu, si bien que les comparaisons avec NULL donnent inconnu plutôt que vrai ou faux ; les filtres WHERE écartent les lignes inconnues, NOT IN avec un NULL ne trouve plus aucune correspondance, et les agrégats ignorent les NULL. Utiliser IS NULL, IS DISTINCT FROM et COALESCE délibérément.
-
Mode maintenance en lecture seule : servir les lectures pendant que les écritures sont suspendues
Pour les déplacements de stockage, les bascules et les migrations longues, un service peut continuer à servir les lectures et refuser les écritures avec un message clair plutôt que de s'éteindre complètement ; default_transaction_read_only de PostgreSQL rend les nouvelles transactions en lecture seule au niveau de la base de données comme filet de sécurité, et le code HTTP 503 avec Retry-After indique aux clients quand réessayer. Le mode nécessite un interrupteur, un message destiné aux utilisateurs et une simulation.
-
Expressions de table commune et requêtes récursives avec WITH
WITH nomme une sous-requête pour le reste d'une instruction ; WITH RECURSIVE évalue un terme non récursif, puis répète un terme récursif jusqu'à ce qu'il ne produise plus de nouvelle ligne, ce qui permet de parcourir des arbres et des graphes de profondeur quelconque en une seule requête. Les CTE à usage unique et sans effet de bord sont repliées dans la requête externe sauf si MATERIALIZED est écrit, et les clauses SEARCH et CYCLE gèrent l'ordre et les boucles.
-
Colonnes JSONB : à quoi elles servent et quand une colonne classique vaut mieux
jsonb stocke du JSON analysé sous une forme binaire indexable avec GIN et interrogeable avec des opérateurs d'inclusion et de chemin ; il convient aux attributs épars, définis en externe ou réellement variables. Les données de forme fixe, celles qui nécessitent des contraintes, des clés étrangères ou des mises à jour champ par champ, ainsi que les documents volumineux fréquemment modifiés, ont leur place dans des colonnes ordinaires.
-
Prévenir les injections SQL avec des requêtes paramétrées
Ne jamais construire du SQL en concaténant des chaînes non fiables ; passer les valeurs comme des paramètres afin que le pilote les envoie séparément de l'instruction, et établir une liste blanche pour tout identifiant qui doit rester dynamique.
-
La mutualisation des connexions à la base de données et ses limites
Chaque connexion PostgreSQL est un processus qui a un coût en mémoire ; les applications devraient conserver un petit pool dimensionné à la concurrence réelle, définir des délais d'expiration à l'acquisition, et ne jamais laisser les gestionnaires de requêtes ouvrir des connexions à la volée.
-
Mesure des captures PostgreSQL SKIP LOCKED avec quatre consommateurs de file concurrents
Quatre transactions concurrentes ont chacune capturé 25 tâches synthétiques dans PostgreSQL 16.15. Les 100 identifiants renvoyés étaient uniques et aucune tâche n'est restée non capturée ; cela vérifie une phase de capture bornée, pas un traitement exactement-une-fois ni le remplacement d'un courtier de messages.
-
Les sagas : des workflows multi-étapes entre services, avec compensation au lieu d'un rollback
Une saga est une séquence de transactions locales réparties dans différents services, chacune déclenchant la suivante ; si une étape échoue, les étapes précédentes sont défaites par des transactions de compensation que la personne qui développe écrit. Les sagas rétablissent la cohérence sans transactions distribuées, mais renoncent à l'isolation : les états intermédiaires sont visibles, et les compensations doivent être conçues, pas supposées.
Lisible par machine : JSON