为什么失败的事务没有使用transactionscope回滚?

lymgl2op  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(450)

我试图实现的是:我从两个不同的数据库调用存储过程。sp在表中有一个简单的insert条目。如果两个事务都成功,则没有问题,但是当我尝试在第二个db sp中抛出异常时,第一个没有回滚。我做错什么了?
c代码:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
{
    // Update DB1
    using (SqlConnection con = new SqlConnection(connectionString1))
    {
        con.Open();
        SqlCommand command1 = new SqlCommand("sp_1", con);
        command1.ExecuteNonQuery();

        // Update DB2 
        using (SqlConnection con2 = new SqlConnection(connectionString2))
        {
            con2.Open();
            SqlCommand command2 = new SqlCommand("sp_2", con2);
            command2.ExecuteNonQuery();
        }
    }
    scope.Complete();
}

db1 sp:

BEGIN
    INSERT INTO TABLE_X1 VALUES(...)
END

db2 sp:

BEGIN
    THROW 51000, 'The record does not exist.', 1; 

    INSERT INTO TABLE_X2 VALUES(...)
END
9lowa7mx

9lowa7mx1#

你需要使用 TransactionScopeOption.Required 启用事务的选项。
如果两个数据库位于同一个sql server上,则使用相同的连接以避免触发分布式事务(如果连接字符串完全相同,则不应发生这种情况)。
transactionscope:避免分布式事务
如果您想利用事务,并且数据库位于不同的服务器(或同一服务器上的不同示例)上,那么就无法避免分布式事务。在这种情况下,启用msdtc,请参见此处的详细信息
https://www.dbrnd.com/2016/11/sql-server-how-to-configure-and-enable-msdtc-microsoft-distributed-transaction-coordinator/

ve7v8dk2

ve7v8dk22#

通过指定 TransactionScopeOption.Suppress 作为transactionscope的构造函数参数,您选择不进行任何事务。
如果使用SUPPRES示例化作用域,则无论是否存在环境事务,它都不会参与事务。用这个值示例化的作用域总是有[sic] null 作为其环境事务。
https://docs.microsoft.com/en-us/dotnet/framework/data/transactions/implementing-an-implicit-transaction-using-transaction-scope
假设此选项适用于您知道其他人可能在调用您的方法之前启动了事务,但您知道您在方法中所做的事情需要在事务之外完成的情况。
因为听起来您想确保事务回滚,所以您可能需要使用 Required (默认值,如果省略参数),或者 RequiresNew .

相关问题