2

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

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

我不相信 create trigger 语句本身有问题。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 中,触发器的创建默认启用。是否可以创建默认禁用的触发器?

还有其他想法吗?

4

5 回答 5

6

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

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

于 2008-10-23T19:52:47.133 回答
4

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

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

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

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

于 2008-10-23T17:52:09.140 回答
2

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

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

于 2008-10-23T17:50:42.450 回答
2

部分问题也可能是触发器本身。您的触发器是否会意外更新表的所有行?测试数据库中的 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

于 2009-06-02T13:40:56.077 回答
0

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

于 2016-06-01T11:14:11.320 回答