Maîtriser PostgreSQL
Thème :
Junior
2 vues ·5/9 leçonsLEÇON 5 : Transactions et Gestion d’Erreurs
5.1 Transactions : ACID et Intégrité
Problématique Entreprise
Un système de paiement doit garantir qu’un débit et un crédit sont toujours exécutés ensemble, sans état intermédiaire visible.
Transaction Basique
-- Transfert d'argent entre comptes
BEGIN;
-- Débit compte source
UPDATE accounts
SET balance = balance - 500
WHERE account_id = 1001;
-- Crédit compte destination
UPDATE accounts
SET balance = balance + 500
WHERE account_id = 2002;
-- Log de la transaction
INSERT INTO transactions (from_account, to_account, amount, transaction_date)
VALUES (1001, 2002, 500, NOW());
COMMIT; -- Valide tout ou ROLLBACK; -- Annule tout
Points de Sauvegarde (SAVEPOINT)
-- Traitement de commande complexe avec étapes
BEGIN;
-- Étape 1 : Créer la commande
INSERT INTO orders (customer_id, order_date, total_amount)
VALUES (123, NOW(), 1500.00)
RETURNING order_id INTO v_order_id;
SAVEPOINT after_order_creation;
-- Étape 2 : Ajouter les lignes
INSERT INTO order_lines (order_id, product_id, quantity, unit_price)
VALUES
(v_order_id, 5001, 2, 500.00),
(v_order_id, 5002, 1, 500.00);
SAVEPOINT after_lines_insertion;
-- Étape 3 : Déduire le stock
UPDATE products
SET stock_quantity = stock_quantity - 2
WHERE product_id = 5001;
UPDATE products
SET stock_quantity = stock_quantity - 1
WHERE product_id = 5002;
-- Si erreur de stock, annuler seulement les mises à jour de stock
-- ROLLBACK TO after_lines_insertion;
-- Tout OK, valider
COMMIT;
Exemple Réel : Système de Réservation
-- Réservation de place de concert (avec gestion de concurrence)
CREATE OR REPLACE FUNCTION book_ticket(
p_event_id BIGINT,
p_user_id BIGINT,
p_seat_number VARCHAR
) RETURNS BIGINT AS $
DECLARE
v_booking_id BIGINT;
v_available_seats INT;
BEGIN
-- Démarrer une transaction implicite
-- 1. Vérifier la disponibilité avec verrou
SELECT available_seats INTO v_available_seats
FROM events
WHERE event_id = p_event_id
FOR UPDATE; -- Verrou exclusif
IF v_available_seats <= 0 THEN
RAISE EXCEPTION 'Plus de places disponibles';
END IF;
-- 2. Vérifier que le siège n'est pas déjà réservé
IF EXISTS (
SELECT 1 FROM bookings
WHERE event_id = p_event_id
AND seat_number = p_seat_number
AND status != 'cancelled'
) THEN
RAISE EXCEPTION 'Siège déjà réservé : %', p_seat_number;
END IF;
-- 3. Créer la réservation
INSERT INTO bookings (event_id, user_id, seat_number, status, booked_at)
VALUES (p_event_id, p_user_id, p_seat_number, 'confirmed', NOW())
RETURNING booking_id INTO v_booking_id;
-- 4. Décrémenter les places disponibles
UPDATE events
SET available_seats = available_seats - 1
WHERE event_id = p_event_id;
-- 5. Retourner l'ID de réservation
RETURN v_booking_id;
EXCEPTION
WHEN OTHERS THEN
-- En cas d'erreur, rollback automatique
RAISE NOTICE 'Erreur réservation : %', SQLERRM;
RETURN NULL;
END;
$ LANGUAGE plpgsql;
-- Utilisation
SELECT book_ticket(100, 456, 'A12');
5.2 Niveaux d’Isolation
Comprendre les Problèmes de Concurrence
| Niveau | Dirty Read | Non-Repeatable Read | Phantom Read | Performance |
|---|---|---|---|---|
| Read Uncommitted | ❌ Oui | ❌ Oui | ❌ Oui | ⚡ Très rapide |
| Read Committed (défaut PG) | ✅ Non | ❌ Oui | ❌ Oui | ⚡ Rapide |
| Repeatable Read | ✅ Non | ✅ Non | ❌ Oui (PostgreSQL: ✅ Non) | 🐢 Moyen |
| Serializable | ✅ Non | ✅ Non | ✅ Non | 🐌 Lent |
Configuration des Niveaux
-- Read Committed (défaut PostgreSQL, recommandé pour 95% des cas)
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- Voit les commits des autres transactions
-- Repeatable Read (pour rapports cohérents)
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Snapshot au début de la transaction
-- Serializable (pour logique métier critique)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Comme si les transactions s'exécutaient en série
Exemple Réel : Report Financier Cohérent
-- Générer un rapport comptable avec snapshot cohérent
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Toutes ces requêtes verront le même état de la base
SELECT SUM(balance) FROM accounts WHERE account_type = 'checking';
SELECT SUM(balance) FROM
Prêt à passer à la suite ?
Vous avez terminé cette leçon sur LEÇON 5 : Transactions et Gestion d'Erreurs. Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.