我们有一个表TABLEA
,其结构为:
ID BINGINT
这是一个IDENTITY(1,1)
PARENTID BIGINT
,它是另一个表的外键列VARCHAR(5)
到VARCHAR(200)
表中预计会有数百万行。由于SQL Server 2005没有很好的方法可以一次性将多行插入到表中,因此我将XML传递给存储过程,后者又解析XML并将行插入表中。
XML的平均大小约为12项。因此负载测试使用12项xml。
我遇到的问题是在负载测试期间发生死锁问题。奇怪的是,当表中没有行时(最初在负载测试期间),当负载进行时会发生死锁。但是如果我们在表中插入大约10000行然后以相同的速率开始负载测试,那么一切都按预期工作。
死锁错误:
事务(进程ID 285)在另一个进程的锁资源上死锁,并被选为死锁牺牲品。重新运行交易
用于插入解析XML的记录的查询(XML中将包含13个项目):
DECLARE @items_xml TABLE (data XML)
DECLARE @p_parent_id BIGINT
DECLARE @p_items_xml_array XML
SET @p_parent_id = 438906
SET @p_condition_entry_array = N'<?xml version="1.0" encoding="utf-16"?> <Items xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Item></Item></Items>'
INSERT INTO @items_xml(data)
SELECT @p_items_xml_array
INSERT INTO TABLEA WITH (ROWLOCK)
(PARENTID, COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN5, COLUMN6, COLUMN7,
COLUMN8, COLUMN9, COLUMN10, COLUMN11,COLUMN12, COLUMN13, COLUMN14, COLUMN15, COLUMN16,COLUMN17)
SELECT
@p_parent_id AS PARENTID,
t.c.value('@F1[1]', 'VARCHAR(32)') AS COLUMN1,
t.c.value('@F2[1]', 'VARCHAR(32)') AS COLUMN2,
t.c.value('@F3[1]', 'VARCHAR(3)') AS COLUMN3,
t.c.value('@F4[1]', 'VARCHAR(32)') AS COLUMN4,
t.c.value('@F5[1]', 'VARCHAR(200)') AS COLUMN5,
t.c.value('@F61]', 'VARCHAR(20)') AS COLUMN6,
t.c.value('@F7[1]', 'VARCHAR(3)') AS COLUMN7,
t.c.value('@F8[1]', 'VARCHAR(8)') AS COLUMN8,
t.c.value('@F9[1]', 'VARCHAR(3)') AS COLUMN9,
t.c.value('@F10[1]', 'VARCHAR(8)') AS COLUMN10,
t.c.value('@F11[1]', 'VARCHAR(3)') AS COLUMN11,
t.c.value('@F12[1]', 'VARCHAR(3)') AS COLUMN12,
t.c.value('@F13[1]', 'VARCHAR(32)') AS COLUMN13,
t.c.value('@F14[1]', 'VARCHAR(200)') AS COLUMN14,
t.c.value('@F15[1]', 'VARCHAR(20)') AS COLUMN15,
t.c.value('@F16[1]', 'VARCHAR(10)') AS COLUMN16,
t.c.value('@F17[1]', 'VARCHAR(32)') AS COLUMN17,
FROM @conditionEntries AS a
CROSS APPLY a.data.nodes('Items/Item') AS t(c)
我的问题是:如果表中的行数不多,以及为什么在表中已包含多行时不会发生死锁,为什么会发生死锁?我使用了ROWLOCK提示,但它没有帮助。