0Pricing
Coding Interview Prep · Lezione

Deadlock, locking e MVCC

Come i database evitano i conflitti e quali compromessi comportano locking e snapshot.

Deadlock, locking e MVCC è una lezione Coding Interview Prep gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Coding Interview Prep, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Coding Interview Prep include 4 lezioni in totale.

Come i database implementano concretamente l'isolamento

I livelli di isolamento sono la promessa; locking e MVCC sono i meccanismi che la rendono possibile. Durante i colloqui si fanno domande su questi aspetti per verificare se comprende cosa accade internamente quando le transazioni entrano in conflitto.

Esistono due strategie generali:

  • Pessimistica (locking): blocca gli accessi in conflitto finché un lock non viene rilasciato.
  • Ottimistica / MVCC: consente a tutti di leggere uno snapshot coerente e rileva i conflitti al momento del commit.

Questa lezione tratta i lock, i deadlock e MVCC, oltre ai compromessi tra queste strategie.

Lock condivisi ed esclusivi

Il locking classico usa due modalità principali:

  • Lock condiviso (S) per le letture. Più transazioni possono mantenere contemporaneamente un lock condiviso sulla stessa riga.
  • Lock esclusivo (X) per le scritture. Una sola transazione può mantenerlo e il lock blocca tutti gli altri lock su quella riga.

La regola è: S è compatibile con S, mentre X non è compatibile con nulla. Chi scrive deve attendere tutti i lettori e i lettori devono attendere chi scrive.

Locking esplicito con SELECT FOR UPDATE

È possibile richiedere un lock di scrittura sulle righe che si stanno soltanto leggendo, per impedire ad altri di modificarle prima che si agisca su di esse. Questo è il metodo standard per evitare gli aggiornamenti persi in un ciclo di lettura-modifica-scrittura.

SELECT ... FOR UPDATE acquisisce lock esclusivi sulle righe; le righe rimangono bloccate fino al COMMIT o al ROLLBACK.

BEGIN;
-- lock the row so no one else can modify it concurrently
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;  -- lock released here

Che cos'è un deadlock?

Un deadlock si verifica quando due o più transazioni mantengono ciascuna un lock di cui l'altra ha bisogno, formando un ciclo dal quale nessuna può uscire.

Il caso da manuale è il seguente: T1 blocca la riga A e poi richiede la riga B; T2 blocca la riga B e poi richiede la riga A. Ciascuna attende indefinitamente l'altra.

I database rilevano questa situazione con un grafo di attesa. Quando viene individuato un ciclo, il motore sceglie una vittima e la interrompe, restituendo un errore di deadlock affinché le altre transazioni possano continuare.

Deadlock: sequenza temporale

Osservi come si incrociano gli ordini dei lock. T1 acquisisce la riga 1 e poi richiede la riga 2; T2 acquisisce la riga 2 e poi richiede la riga 1. Nessuna delle due rilascia il proprio lock, quindi il motore interrompe una delle due transazioni.

La transazione interrotta riceve un errore come deadlock detected e deve essere ritentata. Quella superstite esegue il commit normalmente.

-- T1                                  | -- T2
BEGIN;                                 | BEGIN;
UPDATE accounts SET balance=balance-10  | UPDATE accounts SET balance=balance-10
  WHERE id=1;  -- locks row 1          |   WHERE id=2;  -- locks row 2
UPDATE accounts SET balance=balance+10  | UPDATE accounts SET balance=balance+10
  WHERE id=2;  -- waits for T2         |   WHERE id=1;  -- waits for T1 -> CYCLE
-- one transaction is chosen as victim and rolled back

Prevenire i deadlock

Non è possibile eliminare completamente i deadlock, ma è possibile renderli rari. Le risposte standard durante un colloquio sono:

  • Ordine coerente dei lock: acquisisca sempre le righe nello stesso ordine (per esempio, secondo id crescente). In questo modo si interrompe il ciclo.
  • Mantenga brevi le transazioni: mantenga i lock per il minor tempo possibile.
  • Riduca il livello di isolamento quando è sicuro farlo: meno lock significano meno conflitti.
  • Aggiunga la logica di retry: le transazioni vittime di un deadlock dovrebbero essere ritentate automaticamente.

L'ordine coerente è la soluzione più efficace in assoluto ed è quella che gli intervistatori vogliono sentire per prima.

Granularità dei lock

I lock possono essere acquisiti a diversi livelli, con un compromesso tra concorrenza e overhead:

  • I lock a livello di riga consentono un'elevata concorrenza, ma hanno un costo di gestione maggiore.
  • I lock a livello di pagina o di tabella sono più economici da tracciare, ma bloccano un numero maggiore di transazioni.

Alcuni motori passano dai lock a livello di riga ai lock a livello di tabella quando una transazione coinvolge troppe righe (escalation dei lock). Sapere questo spiega perché un grande UPDATE in blocco può improvvisamente bloccare tutti.

MVCC: l'approccio basato sugli snapshot

MVCC (Multi-Version Concurrency Control) è il meccanismo con cui Postgres, Oracle e InnoDB evitano la maggior parte dei lock di lettura. Invece di bloccare le righe, il database conserva più versioni di ciascuna riga.

Il vantaggio principale, nonché una frase molto apprezzata durante i colloqui, è il seguente: i lettori non bloccano gli scrittori e gli scrittori non bloccano i lettori.

Ogni transazione vede uno snapshot coerente relativo a un determinato istante, mentre gli scrittori creano nuove versioni delle righe invece di sovrascriverle direttamente.

Come funziona MVCC internamente

Quando una riga viene aggiornata, MVCC scrive una nuova versione e conserva quella precedente. Ogni versione contiene metadati relativi all'ID della transazione (in Postgres, xmin e xmax) che indicano quando è diventata visibile e quando è stata sostituita.

Lo snapshot di una transazione determina quale versione può vedere. Le vecchie versioni che nessuna transazione può più vedere diventano tuple obsolete e vengono recuperate in seguito da un processo di pulizia. In Postgres questo processo è VACUUM; non eseguirlo provoca il table bloat, una domanda frequente di approfondimento.

Locking e MVCC: il compromesso

Riassumiamo il confronto in modo chiaro:

  • Locking puro: correttezza semplice da garantire, ma lettori e scrittori si bloccano a vicenda, riducendo la concorrenza.
  • MVCC: ottima concorrenza in lettura, nessun lock di lettura, ma il vantaggio ha il costo di dover conservare e ripulire le versioni (VACUUM, bloat); inoltre servono comunque lock per i conflitti tra scritture.

Anche i motori MVCC usano lock durante le scritture: due transazioni che aggiornano la stessa riga devono essere serializzate. MVCC elimina la contesa tra lettori e scrittori, non quella tra scrittori.

Locking ottimistico e colonne di versione

Oltre all'MVCC a livello di motore, le applicazioni spesso aggiungono il locking ottimistico per le operazioni di lettura-modifica-scrittura che si estendono su sessioni utente lunghe. Si aggiunge una colonna version, la si legge e, al momento dell'aggiornamento, si richiede che la versione corrisponda, incrementandola.

Se un'altra transazione ha aggiornato prima la riga, la versione non corrisponde più, nessuna riga viene modificata e il codice sa di dover ricaricare i dati e ritentare. Non viene mantenuto alcun lock mentre l'utente riflette, quindi la concorrenza rimane elevata. Gli intervistatori apprezzano questa soluzione per la domanda: "come gestirebbe due utenti che modificano lo stesso record?".

-- read: SELECT id, data, version FROM items WHERE id = 1;  -- version = 7
UPDATE items
  SET data = 'new value', version = version + 1
  WHERE id = 1 AND version = 7;
-- if rows affected = 0, someone else changed it: reload and retry

Verifica rapida

Verifichi di aver compreso il concetto fondamentale di MVCC.

Riepilogo: lock, deadlock e MVCC

Ora è in grado di spiegare i meccanismi alla base dell'isolamento:

  • I lock condivisi/esclusivi coordinano gli accessi; SELECT FOR UPDATE acquisisce lock di scrittura espliciti.
  • I deadlock sono cicli di lock; il motore interrompe una transazione vittima e un ordine coerente dei lock ne previene la maggior parte.
  • MVCC conserva le versioni delle righe, in modo che lettori e scrittori non si blocchino a vicenda, al costo della pulizia (VACUUM, bloat).

Associando questi meccanismi ai livelli di isolamento e alle anomalie delle lezioni precedenti, può affrontare un colloquio sulla concorrenza dall'inizio alla fine.

Domande Frequenti

La lezione «Deadlock, locking e MVCC» è gratuita?

Sì — il testo completo di «Deadlock, locking e MVCC» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Coding Interview Prep, passa a CoddyKit PRO. Il corso Coding Interview Prep include 4 lezioni in totale.

Cosa imparerò in «Deadlock, locking e MVCC»?

Come i database evitano i conflitti e quali compromessi comportano locking e snapshot. Eserciti Coding Interview Prep con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Coding Interview Prep?

Non è richiesta alcuna esperienza precedente. Coding Interview Prep su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Deadlock, locking e MVCC»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Coding Interview Prep?

Sì. Ogni lezione Coding Interview Prep include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Spiegazione delle proprietà ACID
  2. I quattro livelli di isolamento
  3. Letture sporche, non ripetibili e fantasma
  4. Deadlock, locking e MVCC
← Torna a Coding Interview Prep