在 SQL Server 2005 上创建触发器需要 30 多分钟

Posted

技术标签:

【中文标题】在 SQL Server 2005 上创建触发器需要 30 多分钟【英文标题】:CREATE TRIGGER is taking more than 30 minutes on SQL Server 2005 【发布时间】:2008-10-23 17:28:57 【问题描述】:

在我们的实时/生产数据库中,我尝试向表中添加触发器,但没有成功。我尝试了几次,但是创建触发器语句完成需要 30 多分钟,我已经取消了它。

该表经常被几个不同的进程读取/写入。我已禁用更新表的计划作业,并在表上的活动较少时尝试,但我无法停止访问表的所有内容。

我认为创建触发器语句本身没有问题。 create trigger 语句在测试环境中成功且快速,并且当向表中插入/更新行时,触发器可以正常工作。虽然当我在测试数据库上创建触发器时,表上没有负载并且它的行数要少得多,这与实时/生产数据库不同(100 对 13,000,000+)。

这是我尝试运行的创建触发器语句

CREATE TRIGGER [OnItem_Updated] 
    ON  [Item]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    IF update(State)
    BEGIN
        /* do some stuff including for each row updated call a stored 
          procedure that increments a value in table based on the 
          UserId of the updated row */
    END
END

在更新行或有很多行时在表上创建触发器是否会出现问题?

在 SQLServer 中,触发器的创建默认启用。是否可以创建默认禁用的触发器?

还有其他想法吗?

【问题讨论】:

【参考方案1】:

问题可能不在于表本身,而在于必须更新才能创建触发器的系统表。如果您在正常流程中执行任何其他类型的 DDL,他们可能会阻止它。

使用 sp_who 找出块的来源,然后从那里进行调查。

【讨论】:

在创建触发器语句运行时运行 sp_who 函数帮助我解决了这个问题。来自另一台服务器的旧会话在表上具有模式稳定性锁时被挂起,这就是我无法创建触发器的原因。【参考方案2】:

我相信 CREATE 触发器会尝试在整个表上加锁。

如果您在该表上有很多活动,则可能需要等待很长时间,您可能会造成死锁。

对于任何架构更改,您都应该真正了解数据库的每个人。

也就是说,通过活动连接进行“小”更改是很诱人的。您应该查看锁/连接以了解锁争用的位置。

【讨论】:

【参考方案3】:

这很奇怪。 AFTER UPDATE 触发器不需要检查表中的现有行。我想您可能无法获得表上的锁来添加触发器。

您可以尝试创建一个基本上什么都不做的触发器。如果你不能创建它,那么这是一个锁定问题。如果可以,那么您可以禁用该触发器,将您的预期代码添加到正文中,然后启用它。 (我不相信您可以在创建过程中禁用触发器。)

【讨论】:

【参考方案4】:

部分问题也可能是触发器本身。您的触发器是否会意外更新表的所有行?测试数据库中的 100 行与 13,000,000 行之间存在很大差异。当您拥有如此庞大的数据集以致无法预测性能时,针对如此小的集合开发代码是一个非常糟糕的主意。对 100 条记录运行良好的 SQL 可以完全锁定数百万个系统数小时。你真的想在 dev 中知道这一点,而不是在你晋升为 prod 的时候。

在触发器中调用存储过程通常是一个非常糟糕的选择。这也意味着您必须遍历记录,这在触发器中是一个更糟糕的选择。触发器必须始终考虑多个记录插入/更新或删除。如果有人插入 100,000 行(如果您有 13,000,000 条记录,则不太可能),然后循环通过基于记录的存储过程可能需要数小时,锁定整个表并导致所有用户想要追捕开发人员并杀死(或至少致残)因为他们无法完成工作。

在您针对与 prod 大小相似的记录集进行测试之前,我什至不会考虑将此触发器放在 prod 上。

我的朋友 Dennis 写了这篇文章,说明了为什么在拥有大量信息时测试少量信息会在 prd 上造成您在 dev 上没有注意到的困难: http://blogs.lessthandot.com/index.php/DataMgmt/?blog=3&title=your-testbed-has-to-have-the-same-volume&disp=single&more=1&c=1&tb=1&pb=1#c1210

【讨论】:

【参考方案5】:

在更改触发器之前运行 DISABLE TRIGGER triggername ON tablename,然后使用 ENABLE TRIGGER triggername ON tablename 重新启用它

【讨论】:

以上是关于在 SQL Server 2005 上创建触发器需要 30 多分钟的主要内容,如果未能解决你的问题,请参考以下文章

SqlDependency通知sql server 2005不会在多个插入上触发

sqlserver2005触发器问题

无法在 View SQL Server 2005 上执行删除

sql server 2005 跨数据库操作

Sql Server 2005 - 插入更新触发器 - 获取更新,插入行

sql 检测更新触发器中修改的字段(sql server 2005)?