【问题标题】:Transaction and TransactionScope isolationTransaction 和 TransactionScope 隔离
【发布时间】:2012-10-05 08:17:37
【问题描述】:

我必须在我的数据库中添加很多信息。添加此信息大约需要 5-7 分钟。我需要添加交易。

我试过了:

try { 
    db.Connection.Open();
    db.Transaction = db.Connection.BeginTransaction(); 
    UpdateTable1();
    UpdateBigTable2();
    ...
    db.Transaction.Commit(); 
} catch {
    db.Transaction.Rollback();  
}

但是当我的数据库更新时,我无法读取数据库或对数据库执行任何操作。

我尝试设置IsolationLevel,但没有任何帮助。

我试过了:

using (var ts = new TransactionScope()) {
    UpdateTable1();
    ts.Complete();
}

但程序在 2-3 分钟后崩溃。

这个解决方案也没有帮助:

var transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
transactionOptions.Timeout = TimeSpan.MaxValue;
using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
    ...
}

如果我设置TransactionScopeOption.Suppress,我可以在更新时访问我的数据库 但在这种情况下,Transaction 不起作用。

【问题讨论】:

  • 当您更新时不仅是更新命令,而且是从外部源插入的东西,我建议您尝试将 SQLBulkCopy 放入暂存数据库,然后从那里复制到您的实际数据库。这应该快得多。 (我曾经通过这种方法完成了 3000-6000 倍)。
  • @TGlatzer 在 transactionscope 中使用 SQLBulkCopy 的完整真实世界代码示例? 隔离级别 ?

标签: c# linq transactions sql-server-ce


【解决方案1】:

是的,如果您启动一个操作大量记录的事务,并且需要很长时间才能完成,那么直接结果是竞争操作将被阻止。对于“可序列化”事务来说尤其是如此,因为它们占用的锁最多(包括键范围锁等)。这是交易的性质;它是 ACID 中的 I。

选项:

  • 不要在一笔大交易中做所有事情
  • 让您的读取操作有意地读取过去锁(这是非常双刃剑 - 可以,但会导致大问题 - 谨慎处理) - 例如NOLOCK 或 @987654322 @。
  • 在完整的 SQL 服务器(不是 CE)上,尝试使用快照隔离

【讨论】:

  • 我有很长的事务要使用 Serializable 插入更多 3000 条记录,但我收到超时错误。
  • @Kiquenet 是的,我可以想象你会;这是很多工作
【解决方案2】:
using (var trans = new TransactionScope(
 TransactionScopeOption.Required, 
    new TransactionOptions
    {
        IsolationLevel = IsolationLevel.ReadUncommitted
    }
))
{
    // Your LINQ to SQL query goes here where you read some data from DB
}

在更新表(插入、删除或更新)时,它们会被锁定,因此如果要读取尚未提交的数据,则可以使用 Transaction IsolationLevel.ReadUncommitted 来允许脏读

【讨论】:

  • OP 的附加说明:竞争查询(被阻止的查询)需要像这样作弊
  • 结果是异常消息“为 TransactionScope 指定的事务,设置了 IsolationLevel,而不是为区域请求的值。参数名称:transactionOptions.IsolationLevel”
  • 这必须与您之前的交易分开,然后才能工作
【解决方案3】:

你试过了吗?

transactionOptions.Timeout = TransactionManager.MaximumTimeout;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2011-04-04
    • 2015-06-19
    • 1970-01-01
    相关资源
    最近更新 更多