【问题标题】:How to simulate DEADLOCK on SQL Server?如何在 SQL Server 上模拟 DEADLOCK?
【发布时间】:2014-05-14 13:04:18
【问题描述】:

我正在尝试在 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 没有给出任何错误。没有发生死锁。为了模拟死锁,我应该改变什么?

【问题讨论】:

  • 为什么读取会导致死锁?
  • 我的数据库管理课程需要演示 SQL SERVER 上的死锁。所以我需要死锁
  • @user3388473 - 您在本课程中使用的是哪本书?谢谢。
  • Connolly T., C. Begg 数据库系统设计、实施和管理的实用方法
  • technet.microsoft.com/en-us/library/aa213039%28v=sql.80%29.aspx 这是一个很好的资源..也许使用排他锁

标签: sql sql-server concurrency deadlock


【解决方案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 发送给客户端。

关闭“会话 1”和“会话 2”的 SSMS 查询窗口以提交(或回滚)任何打开的事务。最后,清理临时表:

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

【讨论】:

  • 如果他们编辑不同的记录,则不会发生死锁。我说的对吗?
  • @SaeedNamati 不,死锁仍然可能发生,例如所有尝试的编辑记录(对于所有不同的 @SPIDs )都在同一页面或已锁定的页面上。为使您的说法属实,应关闭锁升级并为相关表禁用 page_locks。
  • 注意:为了有效地运行它,我所做的是将所有“==”查找/替换为“--”,粘贴到两个查询窗口中,然后在 SSMS 中使用 Alt+Drag 选择我想运行的脚本的各个部分。在 SSMS 2012 及更高版本中,您可以按住 alt 并拖动以创建矩形文本选择
猜你喜欢
  • 1970-01-01
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 2012-01-05
  • 2014-01-17
  • 2012-04-20
  • 2010-10-25
相关资源
最近更新 更多