如果其中一个数据库是只读的,是否会发生分布式事务升级?
我们正在执行从源数据库到目标数据库的导入过程。我们需要以自动化的方式频繁运行这些导入。
源位于与目标不同的服务器上。两者都是 MS SQL 2008。我们使用 Linq2SQL 访问源,使用自定义数据层访问目标。我们永远不会修改源数据库(尽管目前我们不会将其恢复为只读)。但是,现在当我们在 transactionScope 内运行导入时,整个事务会提升为 DTC,因为我们访问不同服务器上的两个数据库。
如果我们将源数据库设为只读,它还会这样做吗?
关于如何避免在这种情况下 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 位吗?或者,我想,既然我真的不关心源头的事务,我可以用 TransactionScope 来抑制该连接包含在任何事务中,对吗?
后续#2:
当你说“打开第二个连接,即使是同一个数据库”时 - 我已经阅读了几个变体:
- “第二个连接”== Connection 对象的第二个实例,即使它与完全相同的连接字符串
- “第二个” connection" == 连接到单独的资源管理器,在 SQL2005 及之前这意味着与上面的 1 相同,但在 SQL2008 上这意味着一个单独的实例(即同一实例上的两个数据库不会升级)
We are doing an import process from a source database to a destination database. We need to run these imports frequently in an automated fashion.
The source is on a separate server than the destination. Both are MS SQL 2008. We access the source using Linq2SQL and the destination using a custom Data Layer. We do not ever modify the source DB (though we do not restore it as read-only at present). However, right now when we run the import within a transactionScope, the entire transaction gets promoted to DTC because we access two DBs on separate servers.
If we were to make the source DB read-only, would it still do this?
Any other suggestions on how to avoid the DTC promotion in this scenario?
Follow-up questions to Remus' answer (thanks again):
Follow-up #1:
My import routine is structured such that it imports records from the source and creates new records in the destination. Like this:
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
}
Are you saying to surround the Linq2Sql bits in a TransactionScope with RequiresNew? Or, I guess, sine I really do not care about transactions at the source, I could surround with TransactionScope with Suppress to that connection's inclusion in any transaction at all, right?
Follow-up #2:
When you say "open a second connection, even to the same Database" - I have read several variations on this:
- "second connection" == second instance of the Connection object even it exactly the same connectionstring
- "second connection" == connection to a separate Resource Manager and on SQL2005 and before this means same as 1 above, but on SQL2008 this means a separate instance (i.e. two DBs on the same instance do not get promoted)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您在事务范围内打开第二个 ADO.Net 连接时,两个连接都将提升为 DTC。即使是到同一个数据库的新连接,也没关系。数据库只读性也与它无关,也不可能与它有任何关系。首先,连接不是特定于数据库的,因为它们可以在打开后更改数据库。其次,只读数据库可以进行大量写入(例如,可以调用 readonlydb.dbo.myProcedure,并且在过程中我可以更新 writabledb.dbo.table)。
如果要避免 DTC,则必须在两个访问层之间使用不同的事务范围(即使用 RequireNew 创建新范围)。
更新
如果可以在范围之外进行读取,那就完美了:
我知道这极不可能,因为第二组读取通常取决于第一次转换/更新的结果。因此,在执行读取时最好抑制范围:
顺便说一句,我假设“使用 linq 读取一些数据”意味着您实际上枚举查询,而不仅仅是创建查询表达式并稍后使用该表达式。我不确切知道事务范围如何与查询表达式交互,但我的假设是该范围适用于查询执行,而不是声明。
The moment you open a second ADO.Net connection inside a transaction scope, both connections will be promoted to DTC. even if is a new connection to the same DB, doesn't matter. Database read-onlyness has also nothing to do with it, and couldn't possible have anything to do with it. First, connections are not database specific since they can change the database after openning. Second, a read only database can do plenty of writes (e.g. can invoke readonlydb.dbo.myProcedure and inside the procedure I can update writabledb.dbo.table).
If you want to avoid the DTC then you must use different transaction scopes between the two access layers (ie. create a new scope with RequireNew).
Update
If is possible to do the reads outside of the scope it would be perfect:
I understand this is higly unlikely though, as probably the second set of reads is dependent o the result of first transform/update usually. So you would best supress the scope when doing the read:
BTW I assume that 'read some data using linq' means u actually enumerate the query, don't just create the query expression and use the expression later. I don't know exactly how a transaction scope interacts with a query expression, but my assumption is that the scope applies to the query execution, not the declaration.