【问题标题】:How does SQL Server treat statements inside stored procedures with respect to transactions?SQL Server 如何处理与事务相关的存储过程中的语句?
【发布时间】:2011-02-07 00:02:40
【问题描述】:

假设我有一个由几个单独的 SELECT、INSERT、UPDATE 和 DELETE 语句组成的存储过程。没有明确的 BEGIN TRANS / COMMIT TRANS / ROLLBACK TRANS 逻辑。

SQL Server 将如何以事务方式处理此存储过程?每个语句都会有隐含的联系吗?还是存储过程只有一个事务?

另外,我如何使用 T-SQL 和/或 SQL Server Management Studio 自己发现这一点?

谢谢!

【问题讨论】:

    标签: sql sql-server stored-procedures transactions


    【解决方案1】:

    只有一个连接,它是用来运行过程的,不管存储过程中有多少条SQL命令。

    由于您在存储过程中没有显式的 BEGIN TRANSACTION,因此每条语句都将自行运行,如果出现任何错误,则无法回滚任何更改。

    但是,如果您在调用存储过程之前发出 BEGIN TRANSACTION,则所有语句都在一个事务中分组,并且可以在存储过程执行后被 COMMITted 或 ROLLBACKed。

    在存储过程中,您可以通过检查系统变量@@TRANCOUNT (Transact-SQL) 的值来确定您是否在事务中运行。零表示没有事务,其他任何内容都显示您处于多少嵌套级别的事务中。根据您的 sql server 版本,您也可以使用XACT_STATE (Transact-SQL)

    如果您执行以下操作:

    BEGIN TRANSACTION
    
    EXEC my_stored_procedure_with_5_statements_inside @Parma1
    
    COMMIT
    

    过程中的一切都被事务覆盖,全部6条语句(EXEC是事务覆盖的语句,1+5=6)。如果你这样做:

    BEGIN TRANSACTION
    
    EXEC my_stored_procedure_with_5_statements_inside @Parma1
    EXEC my_stored_procedure_with_5_statements_inside @Parma1
    
    COMMIT
    

    两个过程调用中的一切都被事务覆盖,全部12条语句(2个EXEC都是事务覆盖的语句,1+5+1+5=12)。

    【讨论】:

    • 所以你说实际上存储过程中的每条语句都形成了自己的事务,即一个内部有五个语句的存储过程在五个事务中执行?
    • 如果过程中没有事务或者过程外包装,那么过程中的每个语句都是一个自治的工作单元。没有真正的交易,因为你不能提交或回滚。如果您将过程调用包装在事务中,则过程中的所有内容都在该单个事务中执行。
    • 谢谢!顺便说一句,我显然失败的代码格式化是怎么做的?
    • @Sleepless,编辑窗口上方有一个工具栏,突出显示完整的代码部分然后单击101010图标,它将在预览窗口中显示为代码。我通常使用编辑器在我的 PC 上编写代码,然后将所有内容缩进 4 个空格,当我将其粘贴到此站点的编辑器中时,它会自动显示为代码。另外,单击橙色帮助“?”图标,这里是链接:stackoverflow.com/editing-help
    【解决方案2】:

    您可以通过创建一个执行简单操作(例如将记录插入测试表)的小型存储过程自行查找。然后开始转;运行 sp_test;回滚;有新纪录吗?如果是这样,则 SP 忽略外部事务。如果不是,那么 SP 只是在事务中执行的另一个语句(我很确定是这种情况)。

    【讨论】:

      【解决方案3】:

      您必须了解事务是会话的状态。会话可以处于显式事务状态,因为在会话中已经执行了至少一个 BEGIN TRANSACTION,只要抛出了命令“BEGIN TRANSACTION”(在进入例程之前或在例程代码内部)。否则,会话的状态处于隐式事务状态。您可以有多个 BEGIN TRANSACTION,但只有第一个会改变会话的行为...其他只会增加 @@TRANCOUNT 全局会话变量。

      隐式事务状态意味着所有 SQL 订单(DDL、DML 和 DCL 命令)都将具有不可见的集成事务范围。

      【讨论】:

      • 如果额外的BEGIN TRANSACTION 语句只增加@@TRANCOUNT - 计算您发出BEGIN TRANSACTION 的次数有什么意义?
      • 因为这是了解您是否处于交易状态的一种方式。当@@TRANSCOUT 大于 0 时,会话的状态是事务性的,而 @@TRANSCOUT = 0 你不是。并且还要知道在事务的真正 COMMIT 之前必须执行多少次 COMMIT。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      相关资源
      最近更新 更多