Guide complet sur la suppression en cascade
Pour comprendre la gestion des relations et des contraintes d'intégrité.
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.
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.
Comment gérer efficacement ces problèmes pour garantir la fiabilité et la disponibilité des systèmes ?

Diagramme des 4 types de problèmes de 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.

| 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 |
-- 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


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 |
-- 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;

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;


// 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


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;
| 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 |
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;
Read Committed pour la plupart des cas (bon compromis). Serializable uniquement pour les transactions critiques.
Déplacez les opérations non critiques (logs, notifications) hors de la transaction.
Toujours accéder aux tables dans le même ordre (ex: table A puis B) pour éviter les deadlocks.
Les index permettent des verrous plus fins (ligne/range) plutôt que des verrous table.
Les deadlocks arrivent. Votre application doit être capable de réessayer automatiquement.
| 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) |
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.
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.
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).
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.
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.
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.
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.