SQL Server 触发器内的存储过程调用是不是隐含线程安全和原子?
Posted
技术标签:
【中文标题】SQL Server 触发器内的存储过程调用是不是隐含线程安全和原子?【英文标题】:Is a stored procedure call inside a SQL Server trigger implictly thread safe and atomic?SQL Server 触发器内的存储过程调用是否隐含线程安全和原子? 【发布时间】:2016-05-18 15:14:52 【问题描述】:我有一个 SQL Server 触发器。老实说,我不太确定触发器是否隐含地遵循 ACID
(Atomicity, Consistency, Isolation, Durability
),但我的触发器目前并没有做任何特别复杂的事情。
现在,我想从触发器中调用一个存储过程。我在存储过程调用和INSERT
语句周围有TRANSACTION
。
我的问题是:如果没有存储过程调用的触发器是线程安全和原子的——至少部分是由于TRANSACTION
——存储过程调用是否会隐含线程安全和原子?
触发器如下所示:
CREATE TRIGGER [triggerInsert_Foobar]
ON [Foobar]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
-- Turns on rollack if T-SQL statement raises a run-time error
SET XACT_ABORT ON
-- Start new transaction
BEGIN TRANSACTION
-- Insert statement for trigger
INSERT INTO Foo ( Col1, Col2 )
SELECT
RTRIM ( LTRIM ( Col1 ) ),
Col2
FROM
INSERTED
-- Call stored procedure (takes no parameters)
EXECUTE sp_executesql N'FoobarApp_DoSomething'
-- Complete transaction
COMMIT TRANSACTION
END;
感谢您的帮助。
其他问题
这个问题已经在几个回答之后准备好了(谢谢)。我提前道歉。
我的触发器和随后的存储过程调用是否遵循 ACID 原则并避免竞争条件和死锁?或者,我需要在触发器和/或存储过程中添加什么来防止竞争条件和死锁吗?
【问题讨论】:
在触发器中使用事务要非常小心。既然你没有错误处理,为什么还要麻烦?请记住,任何插入都有隐式事务。如果您的调用代码正在使用事务创建插入并且出现问题,您将得到一个未处理的异常,因为退出触发器时 tran 计数会有所不同。我会摆脱这里的事务,因为插入已经处理了这个操作的原子性质。 我相信XCT_ABORT ON
负责错误处理;如果事务失败,它会执行回滚——无需显式检查 TRANCOUNT 和回滚。关于在触发器中使用事务,您是说触发器调用的 tran 计数将与我创建的事务中的代码不同,对吗?如果是这样,我知道这怎么可能是一个问题。存储过程调用呢?该线程是安全的和原子的吗?谢谢你的洞察力,肖恩。
【参考方案1】:
底层操作和触发操作被视为原子操作。他们都在一个事务中提交。来自the documentation:
触发器和触发它的语句被视为单个事务...
请注意,触发器(以及 SP 将调用)不会看到触发触发器的表更改。它还没有提交。
【讨论】:
谢谢。有趣的。那么,INSERT 语句在触发器完成之前不会真正提交?这意味着如果我的存储过程依赖于表更改,那么这可能是放置存储过程的错误位置。 @user3621633,您必须将值从INSERTED
传递到 SP,这听起来是个坏主意。
这有点个人喜好/风格,但我倾向于避免触发因素。检查表格时,它们很容易被忽略。对于您正在做的事情,只需调用存储过程并让它更新表以及您在那里所做的任何事情。
@user3621633:如果您需要检查INSERT
语句插入的数据,您可能应该使用AFTER INSERT
触发器,而不是INSTEAD OF INSERT
触发器。在这种情况下,您的触发器在插入操作完成后执行,但仍在该INSERT
statement 的事务中。如果您不喜欢看到的内容,您可以调用 ROLLBACK
并中止 INSERT
事务以停止它。
这是我想要确认的信息。我有一个场景,触发器正在影响我不想要的记录。他们的回答是……脏读……以上是关于SQL Server 触发器内的存储过程调用是不是隐含线程安全和原子?的主要内容,如果未能解决你的问题,请参考以下文章