【问题标题】:Does Distributed Transaction Escalation occur if one of the Databases is READ ONLY?如果其中一个数据库是只读的,是否会发生分布式事务升级?
【发布时间】:2010-01-14 17:32:13
【问题描述】:

我们正在执行从源数据库到目标数据库的导入过程。我们需要以自动化的方式频繁地运行这些导入。

源与目标位于不同的服务器上。两者都是 MS SQL 2008。我们使用 Linq2SQL 访问源,使用自定义数据层访问目标。我们从不修改源数据库(尽管我们目前不将其恢复为只读)。但是,现在当我们在 transactionScope 中运行导入时,整个事务被提升为 DTC,因为我们访问了不同服务器上的两个 DB。

如果我们将源数据库设为只读,它还会这样做吗?

关于如何在这种情况下避免 DTC 促销还有其他建议吗?

对 Remus 回答的后续问题(再次感谢):

跟进#1: 我的导入例程的结构使其从源导入记录并在目标中创建新记录。像这样:

using(var scope = new TransactionScope())
{
   // read some from source db using Linq2Sql
   // transform source info
   // update destination

   // read some more from source db using Linq2Sql
   // transform source info
   // update destination

}

您是说用 RequiresNew 包围 TransactionScope 中的 Linq2Sql 位吗?或者,我想,因为我真的不关心源头的事务,我可以用带有 Suppress 的 TransactionScope 来包围该连接是否包含在任何事务中,对吧?

跟进#2:

当你说“打开第二个连接,即使是同一个数据库” - 我已经阅读了几个关于这个的变体:

  1. "second connection" == Connection 对象的第二个实例,即使它完全相同的连接字符串
  2. “第二个连接”== 连接到单独的资源管理器和 SQL2005 之前,这意味着与上面的 1 相同,但在 SQL2008 上,这意味着一个单独的实例(即同一实例上的两个数据库不会被提升)李>

【问题讨论】:

    标签: sql-server transactions transactionscope msdtc


    【解决方案1】:

    当您在事务范围内打开第二个 ADO.Net 连接时,两个连接都将提升为 DTC。即使是与同一个数据库的新连接,也没关系。数据库只读也与它无关,不可能与它有任何关系。首先,连接不是特定于数据库的,因为它们可以在打开后更改数据库。其次,只读数据库可以进行大量写入(例如,可以调用 readonlydb.dbo.myProcedure 并且在过程中我可以更新 writabledb.dbo.table)。

    如果您想避免 DTC,那么您必须在两个访问层之间使用不同的事务范围(即,使用 RequireNew 创建一个新范围)。

    更新

    如果可以在范围之外进行读取,那将是完美的:

    // read some from source db using Linq2Sql 
    // read some more from source db using Linq2Sql 
    using(var scope = new TransactionScope()) 
    { 
       // transform source info 
       // update destination 
    
       // transform source info 
       // update destination 
    } 
    

    我知道这不太可能,因为第二组读取通常取决于第一次转换/更新的结果。所以你最好在阅读时抑制范围:

    using(var scope = new TransactionScope()) 
    { 
       using(var nada= new TransactionScope(TransactionScopeOption.Supress))
       {
           // read some from source db using Linq2Sql 
           // transform source info 
       }
       // update destination 
    
       using(var nada= new TransactionScope(TransactionScopeOption.Supress))
       {
           // read some more from source db using Linq2Sql
           // transform source info 
       } 
       // update destination 
    } 
    

    顺便说一句,我假设“使用 linq 读取一些数据”意味着您实际上枚举了查询,而不仅仅是创建查询表达式并稍后使用该表达式。我不确切知道事务范围如何与查询表达式交互,但我的假设是范围适用于查询执行,而不是声明。

    【讨论】:

    • 感谢您的回答。我确实有几个后续问题 - 上面的原始问题。
    • 是选项 1:具有相同连接字符串的新 SqlConnection.Open()。他们必须注册到 DTC。因此,需要在 DTC 中注册到 same 资源管理器的两个不同连接。
    • 顺便说一句,与不同 RM 的两个连接显然也需要注册到 DTC,我意识到我之前的评论可能暗示相反的情况,这很愚蠢。
    猜你喜欢
    • 2013-07-02
    • 2021-02-22
    • 2011-06-22
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多