Bases de données · Administration

Comment gérez-vous les problèmes de concurrence d'accès à la base de données ?

Dirty Read, Deadlock, Phantom Read : découvrez les mécanismes d'isolation, verrouillage, timestamping et protocoles de consensus pour garantir l'intégrité de vos données.

Niveau : intermédiaire à avancé | Temps de lecture : 15 min | Mis à jour : avril 2026

Introduction

Les bases de données jouent un rôle essentiel dans les systèmes informatiques modernes, supportant des millions d'opérations simultanées chaque jour. Avec des volumes de données croissants et des utilisateurs accédant simultanément aux mêmes ressources, des problèmes de concurrence peuvent survenir. Ces problèmes, tels que les blocages, les conflits de mise à jour ou les lectures incohérentes, peuvent affecter la performance et l'intégrité des données.

Question centrale :

Comment gérer efficacement ces problèmes pour garantir la fiabilité et la disponibilité des systèmes ?

70%
des pannes de bases de données liées à des problèmes de concurrence
Étude DBTA, 2025
-45%
de deadlocks avec une bonne stratégie de verrouillage
Oracle Performance Study, 2026

Schéma des problèmes de concurrence en base de données

Diagramme des 4 types de problèmes de concurrence

1. Comprendre les problèmes de concurrence

1.1 Définition de la concurrence

La concurrence en base de données survient lorsqu'un ou plusieurs utilisateurs ou processus tentent d'accéder ou de modifier les mêmes données en même temps. Elle est particulièrement critique dans les systèmes transactionnels où les opérations doivent être exécutées de manière fiable et cohérente.

Schéma de la concurrence en base de données

1.2 Types de problèmes de concurrence

Problème Description Conséquence
Lecture sale (Dirty Read) Un utilisateur lit des données modifiées mais non validées Décision basée sur des données qui seront annulées
Lecture non répétable (Non-Repeatable Read) Une même requête retourne des résultats différents Incohérence des analyses
Phantom Read (lecture fantôme) Apparition/disparition de lignes entre deux lectures Agrégations faussées
Deadlock (blocage mutuel) Deux processus s'attendent mutuellement Blocage complet des transactions
Exemple de Deadlock
-- Transaction A
BEGIN;
UPDATE comptes SET solde = solde - 100 WHERE id = 1;
UPDATE comptes SET solde = solde + 100 WHERE id = 2;
COMMIT;

-- Transaction B (simultanée)
BEGIN;
UPDATE comptes SET solde = solde - 50 WHERE id = 2;
UPDATE comptes SET solde = solde + 50 WHERE id = 1;
COMMIT;
-- Résultat : chaque transaction attend le verrou de l'autre → DEADLOCK

Types de problèmes de concurrence

2. Approches pour gérer les problèmes de concurrence

Gestion de la concurrence - vue d'ensemble

2.1 Isolation des transactions

Le concept d'isolation garantit que les opérations d'une transaction n'affectent pas les autres transactions.

Niveau d'isolation Dirty Read Non-Repeatable Read Phantom Read Performance
Read Uncommitted ⚠️ Possible ⚠️ Possible ⚠️ Possible ✅ Maximale
Read Committed (défaut PostgreSQL, SQL Server) ✅ Impossible ⚠️ Possible ⚠️ Possible ✅ Bonne
Repeatable Read (défaut MySQL InnoDB) ✅ Impossible ✅ Impossible ⚠️ Possible  Modérée
Serializable ✅ Impossible ✅ Impossible ✅ Impossible  Réduite
Définir le niveau d'isolation (PostgreSQL)
-- Niveau Read Committed (par défaut)
BEGIN;
SELECT * FROM produits WHERE id = 1;
COMMIT;

-- Niveau Serializable (pour les transactions critiques)
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM produits WHERE id = 1;
UPDATE produits SET stock = stock - 1 WHERE id = 1;
COMMIT;

Niveaux d'isolation des transactions

2.2 Verrouillage (Locking)

Pessimiste
Verrouillage préventif (bloque les accès concurrents)
Optimiste
Vérification à la validation (permet les accès)
Verrouillage pessimiste (SQL Server)
BEGIN TRANSACTION;
-- Verrou exclusif sur la ligne
SELECT * FROM produits WITH (UPDLOCK) WHERE id = 1;
UPDATE produits SET stock = stock - 1 WHERE id = 1;
COMMIT;

Mécanismes de verrouillage

2.3 Gestion des Deadlocks

Bonnes pratiques anti-deadlock :
  • Accédez aux tables dans un ordre cohérent dans toutes les transactions
  • Réduisez la durée des transactions (le temps passé sous verrou)
  • Utilisez des index pour éviter les verrous au niveau table
  • Détectez et gérez les erreurs de deadlock (retry automatique)

Schéma d'un deadlock

2.4 Horodatage (Timestamping)

Contrôle de version optimiste (MongoDB)
// Lecture du document avec sa version
const doc = db.collection.find({ _id: 1 });
const version = doc.version;

// Modification
db.collection.updateOne(
  { _id: 1, version: version },
  { $set: { stock: 99 }, $inc: { version: 1 } }
);
// Si version a changé, la mise à jour échoue

Gestion par horodatage

2.5 Architecture de gestion des transactions distribuées

Cohérence dans les bases distribuées

3. Cas concrets de gestion

3.1 Système de réservation en ligne

Problème : Double réservation de la dernière chambre d'hôtel.
Solution : Verrouillage pessimiste avec MySQL InnoDB.
Réservation sécurisée
START TRANSACTION;
-- Verrou exclusif sur la ligne de la chambre
SELECT * FROM chambres WHERE id = 1 FOR UPDATE;

-- Vérification et réservation
UPDATE chambres SET disponible = FALSE WHERE id = 1 AND disponible = TRUE;

-- Insertion de la réservation
INSERT INTO reservations (chambre_id, client_id, date) VALUES (1, 123, NOW());

COMMIT;

3.2 Gestion des stocks (e-commerce)

Problème : Vente du même produit en stock limité à plusieurs clients.
Solution : Verrouillage optimiste avec Redis (Redlock).

3.3 Gestion documentaire collaborative

Problème : Conflits de version sur document partagé.
Solution : Algorithme de fusion CRDT (comme Google Docs).

4. Outils de surveillance et résolution

Outil Fonctionnalités clés Type
Database Performance Analyzer (SolarWinds) Surveillance des blocages, analyse des deadlocks Payant
pg_stat_activity (PostgreSQL) Visualisation des verrous actifs, requêtes bloquées Gratuit (intégré)
MySQL Performance Schema Métriques de contention, wait events Gratuit (intégré)
Apache Kafka Gestion de l'ordre des messages Open source
PostgreSQL : identifier les verrous actifs
SELECT 
    blocked_locks.pid AS blocked_pid,
    blocked_activity.query AS blocked_query,
    blocking_locks.pid AS blocking_pid,
    blocking_activity.query AS blocking_query
FROM pg_locks blocked_locks
JOIN pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype
    AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
    AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
    AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
    AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
    AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
    AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
    AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
    AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
    AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
    AND blocking_locks.pid != blocked_locks.pid
JOIN pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;

5. Bonnes pratiques

1. Choisissez le bon niveau d'isolation

Read Committed pour la plupart des cas (bon compromis). Serializable uniquement pour les transactions critiques.

2. Minimisez la durée des transactions

Déplacez les opérations non critiques (logs, notifications) hors de la transaction.

3. Accédez aux ressources dans un ordre cohérent

Toujours accéder aux tables dans le même ordre (ex: table A puis B) pour éviter les deadlocks.

4. Utilisez des index adaptés

Les index permettent des verrous plus fins (ligne/range) plutôt que des verrous table.

5. Implémentez une logique de retry

Les deadlocks arrivent. Votre application doit être capable de réessayer automatiquement.

6. Comparatif des approches

Approche Avantages Inconvénients Idéal pour
Verrouillage pessimiste Très sûr, prévisible Risque de deadlocks, moins scalable Réservations, transactions courtes
Verrouillage optimiste Scalable, peu de deadlocks Conflits possibles à la validation Lectures fréquentes, rares modifications
Timestamping Pas de verrouillage, idéal distribué Complexité, coût de versioning Systèmes distribués, NoSQL
Isolation Serializable Garantie maximale Performance réduite, rejeux fréquents Transactions critiques (finance)

7. FAQ — Concurrence en base de données

Quelle est la différence entre un deadlock et un blocage (lock wait) ?

Un blocage (lock wait) est temporaire : une transaction attend qu'une autre libère un verrou, puis continue. Un deadlock est une situation où deux transactions s'attendent mutuellement indéfiniment. Les SGBD résolvent les deadlocks automatiquement en annulant l'une des transactions.

Comment éviter les deadlocks dans une application ?

Principales techniques : (1) accéder aux tables dans un ordre cohérent, (2) garder les transactions courtes, (3) utiliser des index pour éviter les verrous table, (4) implémenter des retry automatiques, (5) éviter les interactions utilisateur au sein d'une transaction.

Quel niveau d'isolation choisir par défaut ?

Read Committed est le meilleur compromis pour la plupart des applications. Il évite les lectures sales sans pénaliser trop la performance. Passez à Repeatable Read ou Serializable seulement si votre application en a besoin (ex: calculs financiers).

Les bases NoSQL gèrent-elles la concurrence ?

Oui, mais différemment. MongoDB utilise le verrouillage optimiste au niveau document. Cassandra propose des "lightweight transactions" (paxos) pour des cas limités. Redis a des commandes atomiques et des verrous distribués (Redlock). Le compromis est souvent entre cohérence forte et performance.

Comment détecter un deadlock sur PostgreSQL ?

PostgreSQL détecte automatiquement les deadlocks et annule la transaction la plus récente avec le message ERROR: deadlock detected. Vous pouvez consulter les logs avec log_lock_waits = on et surveiller pg_stat_activity pour les transactions bloquées.

Qu'est-ce que le 2PC (Two-Phase Commit) ?

Le Two-Phase Commit est un protocole qui garantit la cohérence des transactions distribuées sur plusieurs bases. Phase 1 : chaque base prépare la transaction (promet qu'elle pourra être validée). Phase 2 : toutes les bases valident (commit) ou annulent (rollback). Garantit l'atomicité, mais peut bloquer en cas de panne.

Faites parler vos données
Apprenez les méthodes et les outils pour extraire de la valeur stratégique : Data Science : Le guide complet des méthodes et outils.

Conclusion

La gestion des problèmes de concurrence d'accès à une base de données est cruciale pour garantir la fiabilité, la cohérence et la performance des systèmes informatiques modernes.

À retenir

  • 4 types de problèmes : Dirty Read, Non-Repeatable Read, Phantom Read, Deadlock
  • 4 niveaux d'isolation : Read Uncommitted, Read Committed, Repeatable Read, Serializable
  • 2 stratégies de verrouillage : pessimiste (bloque) vs optimiste (contrôle)
  • Outils de surveillance : pg_stat_activity, Performance Schema, DPA
  • Bonnes pratiques : transactions courtes, ordre d'accès cohérent, retry automatique
Pour aller plus loin : Découvrez notre guide complet sur la suppression en cascade pour comprendre la gestion des relations et des contraintes.
 

Recevez la veille IA & Data qui compte vraiment

 

    Analyses claires, outils concrets et tendances IA sans bruit.     Rejoignez les lecteurs de IANA Data.