我在为新创建的空表添加简单的外键约束时遇到很多问题。参考表是一个很小的参考表,其中有少于40个记录,但它被引用了很多。
这是发生了什么:新表成功创建,但是当添加FK约束时,它会“思考”很长时间并增加CPU负载。内存使用量增加,服务器开始像疯了一样分页并且没有响应(连接超时)。取消查询没有帮助。唯一有效的是重启服务器,这是非常昂贵的。
这是我正在尝试运行的脚本。我希望SQL服务器专家可以提供帮助。 THX!
USE [my_db]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyNewTable](
[Column1ID] [int] NOT NULL,
[Column2ID] [int] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyNewTable] WITH CHECK ADD CONSTRAINT [FK_MyNewTable_Column1ID] FOREIGN KEY([Column1ID])
REFERENCES [dbo].[ReferenceTable] ([Column1ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[MyNewTable] CHECK CONSTRAINT [FK_MyNewTable_Column1ID]
GO
编辑:ReferenceTable是一个小表,看起来像这样:
[Column1ID] [int] IDENTITY(1,1) NOT NULL,
[TxtCol1] [varchar](50) NOT NULL,
[TxtCol2] [varchar](50) NOT NULL,
[TxtCol3] [varchar](200) NOT NULL,
[TxtCol4] [nvarchar](2000) NOT NULL,
[TxtCol5] [varchar](200) NOT NULL,
[BitCol1] [bit] NOT NULL,
[TxtCol6] [varchar](200) NOT NULL,
[NumCol1] [smallint] NOT NULL,
[ExternalColumnId] [int] NOT NULL,
[NumCol2] [int] NOT NULL
Column1ID被其他表(FK)引用很多。 ExternalColumnId是另一个表的FK。在其中一个ALTER TABLE调用期间发生此问题。不幸的是,这些都是一起运行的,所以我无法说出哪一个引起了它。
编辑:一旦数据库进入“思考”模式,可以通过将其切换到单一模式然后再返回多用户模式来恢复它。它比重启服务器要好得多,但仍然不能接受。
答案 0 :(得分:4)
随机想:你有没有打开任何交易?
ALTER TABLE将需要独占访问(与大多数DDL一样),它可能被模式锁阻塞,而模式锁又会阻止ReferenceTable,而后者又会阻止其他查询......
答案 1 :(得分:0)
我建议单独运行每个查询批处理。
首先,创建表并查看是否成功。
接下来,尝试使用WITH NOCHECK
而不是WITH CHECK
自行添加外键约束。在创建约束时,WITH NOCHECK
将禁止在MyNewTable.Column1ID
中对引用表的列中的值进行任何验证。如果MyNewTable
为空或行数很少,我认为这不会产生太大影响,但我遇到过你所描述的症状 - 除了得到新约束的表中有数百万行
最后,运行最后一批尝试在新约束上设置WITH CHECK
。如果这个陷入困境,您可能只需要保留新的FK集WITH NOCHECK
,但不建议这样做,因为查询优化器会忽略定义的约束WITH NOCHECK
,直到它们被设置回{{1 }}
答案 2 :(得分:0)
如果此问题可重现,我建议您打开Microsoft支持案例。可能是一个错误,你正在打它。如果发现这是一个已知问题,他们会向您退还打开案件的费用。
答案 3 :(得分:0)
需要研究的一些事情 - 不是解决方案,但它们可能会带来一些东西。
是否定义了任何触发器?
在创建新表时是使用还是访问数据库,还是空闲?
是否有任何事情(在部署或其他情况下)更新引用表中的Column1ID,或删除该表中的行?
引用表中的Column1ID是否存在主键或唯一约束? (你没有列出一个,但我认为如果没有SQL,SQL会立即失败。)