【发布时间】:2014-07-02 15:59:22
【问题描述】:
DB中有两个表,Audit和AuditField,创建表代码如下:
-- Primary key: ID
CREATE TABLE [dbo].[Audit](
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[TypeName] [varchar](50) NOT NULL
)
GO
-- Primary key: ID
CREATE TABLE [dbo].[AuditField](
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[AuditID] [int] NOT NULL,
[Field1] [varchar](50) NOT NULL
)
GO
-- Set foreign key on AuditField table
ALTER TABLE [dbo].[AuditField]
ADD CONSTRAINT [FK_AuditFiled_Audit] FOREIGN KEY([AuditID])
REFERENCES [dbo].[Audit] ([ID])
GO
然后我准备了一些测试数据:
DECLARE @audit TABLE
(
ID int not null,
TypeName varchar(50)
)
DECLARE @auditField TABLE
(
AuditID int not null,
Field1 varchar(50)
)
-- ADD TEST DATA
DECLARE @i int = 1
DECLARE @rowCount int = 500
WHILE @i<=@rowCount
BEGIN
INSERT INTO @audit
VALUES(@i, 'SomeTypeName')
INSERT INTO @auditField
(AuditID,Field1)
VALUES(@i,'SomeThing')
SET @i += 1
END
最后,我运行以下事务将测试数据插入到这两个表中:
begin transaction
INSERT INTO dbo.Audit
SELECT TypeName
FROM @audit
ORDER BY ID
declare @lastIdentity int = @@identity
declare @offSet int = @lastIdentity - @rowCount
INSERT INTO dbo.AuditField
SELECT AuditID+@offSet AS AuditID, Field1
FROM @auditField
ORDER BY AuditID
commit transaction
当这个事务并发运行时,发生死锁,一个进程失败,另一个进程出错:
消息 547,级别 16,状态 0,第 40 行 INSERT 语句冲突 具有 FOREIGN KEY 约束“FK_AuditFiled_Audit”。冲突 发生在数据库“MyDB”、表“dbo.Audit”、列“ID”中。
在 Audit 和 AuditField 表上没有触发器。 很抱歉代码的格式,我真的需要一个答案为什么会发生这种死锁,谢谢。
有一点要明确,AuditField 表的数据来自@auditField,正如@Bogdan 的回答我这样改写:
begin transaction
INSERT INTO dbo.Audit
OUTPUT inserted.ID INTO @temp
SELECT TypeName
FROM @audit
INSERT INTO @idMapping
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS RowNumber, ID
FROM @temp
INSERT INTO dbo.AuditField
SELECT m.ID AS AuditID, Field1
FROM @auditField af
INNER JOIN @idMapping m ON af.AuditID = m.RowNumber
commit transaction
【问题讨论】:
-
现在应该没问题了,因为
INSERT INTO dbo.AuditField ...只会在同一事务中插入INSERT INTO dbo.Audit ...生成的AuditID值。
标签: sql-server database foreign-keys deadlock