2013-02-25 170 views
1

我有一个名为Products的表,它有很多列。避免并发删除造成死锁

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

表结构: 创建表产品 (例如唯一标识符, 插入日期时间, COL1,COL2 ,...)

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

查询1: “设置事务隔离READUNCOMMITTED 删除产品(NOLOCK)P其中例如= 'XXXX-XXX-XXX-XX'”

QUERY2: “设置事务隔离READUNCOMMITTED 删除P从产品(NOLOCK)其中插入< = DATEADD(HH,-10,GETDATE())”

注:非聚簇索引是在实例列创建。

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

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

+0

看看这个http://stackoverflow.com/questions/9952137/multi-threading-c-sharp-application-with-sql-server-database-calls/10035988#10035988 – Phil 2013-02-25 18:41:30

回答

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 set (allow_row_locks = on, allow_page_locks = off) 
1

首先,除了独占锁之外,您可以对这些删除语句执行锁定。您的isolation level and NOLOCK hints are being ignored by Sql Server

(Nolock)仅适用于SELECT声明。

两个建议:

instance的非聚集索引更改为聚集索引。但只有这样做,如果你可以改变NEWID()NEWSEQUENTIALID()

二,而不是执行delete删除超过10小时的记录...考虑implementing rolling partitions。这将消除由您的其他delete操作导致的清理引起的任何争用。