web-dev-qa-db-fra.com

Comment simuler DEADLOCK sur SQL Server?

J'essaie de simuler un blocage sur SQL Server.

_|worker_id|salary|
1|1        |100   |
2|2        |300   |

La transaction 1 s'est terminée en 5 secondes.

/* TRANSACTION 1*/
Use dbmcw;

DECLARE @sal1 INT, @sal2 int;

BEGIN TRAN;

SELECT @sal1 = salary
FROM dbo.deadlock_demonstration WITH(UPDLOCK) 
WHERE worker_id = 1;

WAITFOR DELAY '00:00:05.000';

SELECT @sal2 = salary
FROM dbo.deadlock_demonstration WITH(UPDLOCK)
WHERE worker_id = 2;

COMMIT TRAN;

La transaction 2 s'est terminée en 3 secondes.

/* TRANSACTION 2*/
Use dbmcw;

DECLARE @sal1 INT, @sal2 int;

BEGIN TRAN;

SELECT @sal2 = salary
FROM dbo.deadlock_demonstration WITH(UPDLOCK)
WHERE worker_id = 2;

SELECT @sal1 = salary
FROM dbo.deadlock_demonstration WITH(UPDLOCK)
WHERE worker_id = 1;

COMMIT TRAN;

SQL Server ne donne aucune erreur. Aucun blocage ne s'est produit. Que dois-je changer pour simuler un blocage?

31
user3388473

Vous pouvez créer un blocage en suivant les étapes ci-dessous. Créez d'abord les tables temporaires globales avec des exemples de données.

--Two global temp tables with sample data for demo purposes.
CREATE TABLE ##Employees (
    EmpId INT IDENTITY,
    EmpName VARCHAR(16),
    Phone VARCHAR(16)
)
GO

INSERT INTO ##Employees (EmpName, Phone)
VALUES ('Martha', '800-555-1212'), ('Jimmy', '619-555-8080')
GO

CREATE TABLE ##Suppliers(
    SupplierId INT IDENTITY,
    SupplierName VARCHAR(64),
    Fax VARCHAR(16)
)
GO

INSERT INTO ##Suppliers (SupplierName, Fax)
VALUES ('Acme', '877-555-6060'), ('Rockwell', '800-257-1234')
GO

Ouvrez maintenant deux fenêtres de requête vides dans SSMS. Placez le code de la session 1 dans une fenêtre de requête et le code de la session 2 dans l'autre fenêtre de requête. Exécutez ensuite chacune des deux sessions étape par étape, en effectuant des allers-retours entre les deux fenêtres de requête, si nécessaire. Notez que chaque transaction a un verrou sur une ressource sur laquelle l'autre transaction demande également un verrou.

Session 1                   | Session 2
===========================================================
BEGIN TRAN;                 | BEGIN TRAN;
===========================================================
UPDATE ##Employees
SET EmpName = 'Mary'
WHERE EmpId = 1
===========================================================
                             | UPDATE ##Suppliers
                             | SET Fax = N'555-1212'
                             | WHERE SupplierId = 1
===========================================================
UPDATE ##Suppliers
SET Fax = N'555-1212'
WHERE SupplierId = 1
===========================================================
<blocked>                    | UPDATE ##Employees
                             | SET Phone = N'555-9999'
                             | WHERE EmpId = 1
===========================================================
                             | <blocked>
===========================================================

Une impasse résulte; une transaction se termine et l'autre transaction est abandonnée et le message d'erreur 1205 est envoyé au client.

Fermez les fenêtres de requête SSMS pour "Session 1" et "Session 2" pour valider (ou restaurer) toutes les transactions ouvertes. Enfin, nettoyez les tables temporaires:

DROP TABLE ##Employees
GO
DROP TABLE ##Suppliers
GO
46
Dave Mason