当通过DataReader
从SQL服务器查询返回大型数据集时,我们的数据层存在一些问题。当我们使用DataReader
来填充业务对象并将它们序列化回客户端时,获取可能需要几分钟(我们向用户显示进度:-)),但是我们发现有一些非常强硬的锁定进行on受影响的表,导致其他更新被阻止。
所以我想我的稍微天真的问题是,由于执行查询而被取出的锁实际上放弃了什么?我们似乎发现锁定仍然存在,直到DataReader
的最后一行被处理并且DataReader
实际上已经关闭 - 这看起来是否正确?关于DataReader
如何在幕后工作的快速101将是伟大的,因为我努力寻找任何体面的信息。
我应该说,我意识到锁定问题是主要问题,但我只是关注DataReader
的行为。
因此,从1,2和3我们可以看到,在高隔离级别下运行查询的慢客户端将导致共享锁保持很长时间。
现在你需要详细说明你观察的内容:
您最好的选择可能是snapshot isolation(至少需要SQL Server 2005),可以是快照隔离级别,也可以是读取提交的快照。这将完全消除锁定问题,但会在tempdb上产生一些IO压力。
其他解决方案是使用游标,但是对现有代码库具有侵扰性,复杂且仍然容易出错(必须使光标类型正确)。
顺便说一句,我不建议更改客户端行为。我现在假设你在SqlDataReader循环中读取它们时正在编组业务对象,这就是这样做的方法。预先读入内存然后编组可能会在大型数据集上添加更多问题。
选择临时表会减少锁定持续时间
select blah from tbl into #temp << locks held and released
select * from #temp << take all the time you want now