我有一个多流程方案。因此,多个Windows应用程序从不同的PC连接到数据库。
我有两个表的简单构造:
tblJobs被大量使用。记录由INSERT INTO
插入。所有较大的操作首先在tblJob上执行TABLOCKX
,以防止出现任何死锁情况。从记录中删除记录,并使用简单的DELETE
给出作业的特定ID。 tblJobs中的条目数约为100-5000条记录。每行包含5个INT,1个DATETIME字段和1个UID。所以桌子真的很小。因此,它不是大量记录,但是我们在表上运行着永久的INSERT/DELETE
语句。
我们在客户站点上发现了运行我们的软件并使用SQL Server 2008(标准版)的问题。 我们实施了一些测试程序,并隔离出一个真正的奇怪效果,这种效果在我们的客户身上出现。
SELECT COUNT(*) FROM tblJobs WHERE Data=…
来检查我们收集的信息是否仍然正确。通常,此查询应始终返回1!SELECT * FROM tblJobs
就像执行下一个操作一样不会显示预期的记录。 (两个SELECT语句都不属于一项事务)隔离级别应为READ COMMITED
。但是我看到的情况是我看到与READ UNCOMMITED
的会话。在寻找解决方案以及我们遇到问题的原因时,我找到了该SO链接SQL Server: Isolation level leaks across pooled connections
我找不到某些会话显示永久隔离级别READ COMMITED
的原因。发生错误时,我也无法说出隔离级别。
我也可以说这仅在SQL Server负载很重的情况下发生。如我所见,服务器没有内存压力。
我做什么:
我们还创建了具有相同需求和软件的测试方案,但我们永远无法解决问题。
对程序进行更改并将其推广给客户并非易事。因此,我无法快速提供新信息。
所以我的问题:
在隔离级别为READ COMMITED
或READ UNCOMMITED
的情况下,是否存在SELECT COUNT(*)语句可能丢失先前返回的记录而又未返回的记录的情况?是否存在导致记录不出现在SELECT语句中的锁定注意事项?
答案 0 :(得分:0)
是的。当您处于“读取未提交”模式时,查询可以读取事务日志中尚未完全提交的数据,因此仍具有某种形式的锁定。在“读取已提交”中,您的读取将请求共享锁,并且如果插入具有独占锁,则必须等待。然后,您必须考虑要处理的是行锁,表锁还是页锁。可能发生页面锁定吗?第A行恰好与第Z行存在于同一页面上,正在更新第A行,因此您要等到Z行完成才能找到它。有人打开了允许页面锁定的设置吗? 您还应该知道,在查询中使用With(nolock)会将查询的该部分放入“读未提交”中。