从正由另一个进程添加的表中删除行时是否会发生死锁?


2

当原始表正在使用时,我必须将表中的数据存档到另一个表中。归档过程是将行复制到另一个表中,然后从原始表中删除行。要归档的行由具有Identity属性的列选择。

一个因素是正在使用存档行的表 - 在存档过程运行时,新行将写入表中。这是一个无法停止的24/7应用程序。

要删除的行位于Identity列编号的低端,而新行将添加到表的末尾。

我担心的是僵局。是否有可能在两个进程之间发生死锁?

档案流程将从存储过程运行?我应该将DEADLOCK_PRIORITY设置为LOW以确保如果发生死锁确实会导致存档过程被杀死而不是正在运行的应用程序吗?

我还应该设置TRANSACTION ISOLATION LEVEL吗?

谢谢

表定义:

    CREATE TABLE [dbo].[DummyName](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Payment Reference] [nvarchar](18) NULL DEFAULT (N''),
    [Payment Amount] [decimal](28, 10) NULL,
    [Payment Date] [datetime] NULL,
    [Payer ID] [nvarchar](34) NULL DEFAULT (N''),
    [Payer Account] [nvarchar](174) NULL DEFAULT (N''),
    [Payer Name] [nvarchar](174) NULL DEFAULT (N''),
    [Payer Type] [nvarchar](35) NULL DEFAULT (N''),
    [Bank Reference] [nvarchar](16) NULL DEFAULT (N''),
...

指数定义:

ALTER TABLE [dbo].[DummyName] ADD PRIMARY KEY NONCLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Answers:


3

要归档的行由具有Identity属性的列选择

在这种情况下,您将在索引的末尾插入行,并从头开始删除行。所以那里 不能 重叠锁会导致死锁。

这假设您的归档过程不会同时运行。多个并发存档操作可能会相互死锁,因为它们将在相同的行范围内运行。例如,您应该确保不将其作为SQL Server代理作业进行调度。

只需确保在归档后不要从“实时”表中一次删除太多行,因为这可能会导致锁定升级(这听起来像是在您的情况下不受欢迎)。查看Michael Swart关于以促进性能和并发性的方式进行批处理的主题的优秀文章: 编写脚本时要小心

即使你的主表是一个 ,对于死锁,你应该还可以,因为所有的查询都倾向于在非聚集PK上寻找并使用RID从那里删除。您可能会在堆本身内遇到页面级别阻塞(或死锁),具体取决于很多因素,但如果没有看到工作负载,就很难确定。

我应该将DEADLOCK_PRIORITY设置为LOW以确保如果发生死锁确实会导致存档过程被杀死而不是正在运行的应用程序吗?

是的,这是一个合理的步骤。正如您所提到的,这是一种确保存档工作负载在并发方面重新确定优先级的好方法。

我还应该设置TRANSACTION ISOLATION LEVEL吗?

默认隔离级别( READ COMMITTED )在这种情况下应该没问题。


@LondonKiwi谢谢!只要你的 SELECTDELETE 在Id列上,所有操作都应该在非聚集PK上寻找并避免阻塞/死锁。你有没有理由把这张桌子留下来?
jadarnel27

该数据库是我们使用的第三方软件包的一部分。它是如何交付的。我不愿改变它,因为我说它是我们使用的24/7系统的一部分。
LondonKiwi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.