- Apri due connessioni in parallelo, come due istanze di
psql
o due finestre di query in pgAdmin (ognuna ha la propria sessione). - Avvia una transazione in ogni connessione.
BEGIN;
- Esegui a turno comandi in conflitto tra loro.
- Prima che tu possa eseguire il commit, verrà eseguito il rollback di uno dei due con un'eccezione deadlock.
- Potresti voler ripristinare l'altro.
ROLLBACK;
Esplicitamente tabelle di blocco è semplice come:
LOCK tbl;
Il blocco delle righe può essere eseguito con:
SELECT * FROM tbl WHERE boo = 3 FOR UPDATE;
Oppure FOR SHARE
ecc. Dettagli nel manuale.
(O implicitamente con UPDATE
o DELETE
.)
Esempio
Il tuo esempio aggiunto non può bloccarsi. Entrambi provano a prendere prima lo stesso blocco sulla stessa riga della stessa tabella. Il secondo aspetterà che il primo finisca.
Esempio per produrre effettivamente un deadlock (devono esistere righe o non verrà preso alcun blocco):
Transaction 1 Transaction 2
BEGIN;
BEGIN;
SELECT salary1
FROM deadlock_demonstration
WHERE worker_id = 1
FOR UPDATE;
SELECT salary1
FROM deadlock_demonstration
WHERE worker_id = 2
FOR UPDATE;
UPDATE deadlock_demonstration
SET salary1 = 100
WHERE worker_id = 2;
UPDATE deadlock_demonstration
SET salary1 = 100
WHERE worker_id = 1;
--> ... 💣 deadlock!
Risultato
L'utente OP3388473 ha contribuito a questo screenshot dopo aver verificato la soluzione: