Подтвердить что ты не робот

Как имитировать DEADLOCK на SQL Server?

Я пытаюсь имитировать тупик на SQL Server.

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

Транзакция 1 завершена за 5 секунд.

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

Транзакция 2 завершена за 3 секунды.

/* 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 не дает никаких ошибок. Тупика не произошло. Что я должен изменить, чтобы имитировать тупик?

4b9b3361

Ответ 1

Вы можете создать тупик, используя шаги, показанные ниже. Сначала создайте глобальные временные таблицы с образцами данных.

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

Теперь откройте два открытых окна запросов в SSMS. Поместите код для сеанса 1 в одно окно запроса и код для сеанса 2 в другое окно запроса. Затем выполните каждую из двух сессий шаг за шагом, переходя туда и обратно между двумя окнами запросов по мере необходимости. Обратите внимание, что каждая транзакция имеет блокировку ресурса, в которой другая транзакция также запрашивает блокировку.

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

Результаты взаимоблокировки; одна транзакция завершается, а другая транзакция прерывается, и сообщение об ошибке 1205 отправляется клиенту.

Закройте окна запросов SSMS для "Сессия 1" и "Сессия 2", чтобы совершать (или откатывать) любые открытые транзакции. Наконец, очистите временные таблицы:

DROP TABLE ##Employees
GO
DROP TABLE ##Suppliers
GO