我正在使用 Dapper,但这同样适用于 ADO.NET 代码。
我在一个 Web 应用程序上进行了一项操作,该操作会更改数据库中的许多状态。为了确保要么全有要么全无的结果,我使用事务来管理它。为此,我的所有
Repository
类共享一个连接(根据请求实例化)。通过我的连接,我可以拨打 Connection.BeginTransaction()
。
但是,此操作有时可能需要一段时间(例如 10 秒),并且在执行此操作时会锁定一些经常读取的表。我希望允许其他线程上的其他存储库在发生这种情况时继续而不锁定。
看来我需要做两件事才能实现这一点:
1) 将
IsoloationLevel
设置为 ReadUncommited:
_transaction = Connection.BeginTransaction(IsolationLevel.ReadUncommitted);
2)对于所有其他不需要事务的连接,我仍然需要将这些连接注册到事务中,以便我可以再次设置
ReadUncommited
。如果我不这样做,那么它们在等待长时间运行的操作完成时仍然会锁定。
那么这是否意味着我需要所有连接才能开始交易?这听起来很昂贵而且性能不佳。我这里还缺少其他解决方案吗?
谢谢
请注意,使用锁与不使用锁之间存在权衡,这关系到性能与并发控制。因此,我认为你不应该一直使用
ReadUncommited
。
如果您尝试在不需要被此长时间运行的事务阻止的所有其他事务上使用
ReadUncommited
,它们将意外地 也不会被其他事务阻止。
一般情况下,当性能是第一要务且不需要数据准确性时
,我们使用此隔离级别我想允许其他线程上的其他存储库继续运行而无需 发生这种情况时锁定。
我认为您可以尝试
IsolationLevel.SnapShot
仅在进行长时间读取工作的事务上:https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx
摘自链接:
术语“快照”反映了以下事实: 事务查看数据库的相同版本或快照,基于 数据库此时的状态 交易开始。 未获取底层数据行的锁 或快照事务中的数据页,这允许其他 执行的交易不会被先前未完成的交易阻止 交易。 修改数据的交易不会阻塞交易 读取数据,并且读取数据的事务不会阻塞 写入数据的事务,就像默认情况下通常那样 SQL Server 中的 READ COMMITTED 隔离级别。这种非阻塞 行为还显着降低了死锁的可能性 复杂的交易。
请注意,如果有大量修改,
tempdb
中可能会生成大量数据用于版本存储。