【问题标题】:RETURN inside a Trigger, safe?在触发器内返回,安全吗?
【发布时间】:2018-05-24 06:41:36
【问题描述】:

我正在尝试查找有关 RETURN 在触发器内的效果的信息。我能找到的唯一文档是它“释放”了触发器。

https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-2017#optimizing-dml-triggers

我问的原因是最近添加的触发器会导致一些死锁问题,即使触发器是空的也是如此。

这些示例非常荒谬(为什么要检索刚刚插入的数据),但这就是它的工作方式。生成这些语句的代码非常陈旧。

“空”触发器的主体

BEGIN
    SET NOCOUNT ON;
END

在 Table1 上启用了空触发器

BEGIN TRANSACTION
    INSERT INTO Table1....                 -- Table1 becomes locked until transaction is committed

    SELECT * FROM Table1 WHERE ID = X...   -- deadlock

    INSERT INTO Table2...
COMMIT TRANSACTION

空触发器已禁用

BEGIN TRANSACTION
    INSERT INTO Table1....                 -- Table1 DOES NOT BECOME LOCKED

    SELECT * FROM Table1 WHERE ID = X...

    INSERT INTO Table2...
COMMIT TRANSACTION

在触发器末尾添加RETURN会释放锁,防止死锁。

这样安全吗?我唯一能想到的是如果触发器修改了它所在的表,释放锁可能会导致脏读。

【问题讨论】:

  • 什么版本的 SQL Server,什么是“空触发器”——没有正文就不能有触发器。
  • @RhysJones Microsoft SQL Server 2014 (SP2-CU8)。正文设置为无计数;。正文为 PRINT("") 时的行为相同
  • 您的示例不仅仅是荒谬的,因为在触发器中选择数据是一件棘手的事情。很明显,仅仅拥有一个触发器本身不会阻塞任何东西,你需要另一个事务来处理它。你能给我们一个最小的、可重现的场景,任何人都可以在 SSMS 中运行,还是它依赖于此处未显示的复杂的其他代码?

标签: sql-server tsql database-trigger


【解决方案1】:

要回答您的问题,是的,在触发器中使用 RETURN 是非常安全的。如果没有要处理的行,它通常在复杂触发器开始时立即退出。像这样;

IF (@@ROWCOUNT_BIG = 0)
RETURN;

但是,一定有其他原因会导致死锁。请参阅 Gail Shaw 的优秀博客 SQL Server Deadlocks by Example 并查看死锁图,看看它是否为您提供了更多关于问题所在的线索。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多