避免并发删除死锁

时间:2013-02-25 18:12:45

标签: sql sql-server deadlock

我有一个名为Products的表,它有很多列。

这是一个用于报告目的的临时表。数据将通过多个用户请求同时处理到此表。(单独存储过程对此表进行DML操作)

表格结构: 创建表产品 (实例uniqueidentifier, 插入日期时间, col1,col2,...)

插入的列将使用GETDATE()填充,以便在插入数据时使用。实例列具有newid()值。一个用户请求将具有一个唯一ID;可能有百万行。以下是将同时执行的查询,这会导致死锁。请告诉我

查询1: "设置事务隔离readuncommitted 从产品中删除P(Nolock)其中instance =' XXXX-xxx-xxx-xx'"

QUERY2: "设置事务隔离readuncommitted 从产品中删除P(Nolock),其中插入< = DATEADD(hh,-10,getdate())"

注意:非聚集索引是在实例列上创建的。

请告诉我在这种情况下我可以使用哪种锁。

注意我无法使用主键,因为当我向表中插入1000万行时(这是一个事务;有20个并发转换)消耗时间。 该报告应该尽快生成。我的程序有多个35个DML语句,大约有15个DELETE语句用于实例列和其他列(表格中的DElete,其中instance = @instance和col1 = @ col1)。

2 个答案:

答案 0 :(得分:5)

(1)您应该停止使用read uncommitted隔离。至少使用read committed

(2)您可以尝试避免死锁,例如确保您的不同事务以相同的顺序访问数据库对象等等。这值得一读 - http://support.microsoft.com/kb/169960

(3)禁用表的锁升级(更细粒度的锁,以便更好的并发性,但更多的锁开销):

ALTER TABLE Products SET (lock_escalation = disable)

(4)禁止页面锁定,并允许索引上的行锁定(意味着您无法对索引进行碎片整理,但仍可以重建它们):

ALTER INDEX [<YourIndex>] ON Product WITH (allow_row_locks = on, allow_page_locks = off)

答案 1 :(得分:1)

首先,除了独占锁之外,你无法对这些删除语句采取锁定。您的isolation level and NOLOCK hints are being ignored by Sql Server

  

(Nolock)仅适用于SELECT声明。

两个建议:

instance上的非聚集索引更改为聚簇索引。但是,只有在您将NEWID()更改为NEWSEQUENTIALID()时才能执行此操作。

其次,不要执行delete来删除超过10小时的记录......请考虑implementing rolling partitions。这将删除您使用其他delete操作清理所造成的任何争用。