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