我正在使用链接到SQL Server 2008 R2后端的Access 2007前端,并且遇到了我认为即使是简单的直通选择查询导致的奇怪锁定行为。更具体地说:
我有一个简单形式的直通查询" SELECT * FROM tbl_A"。如果我在访问(正常数据表查询视图)中打开此查询并且该表具有足够多的记录(大约> 100条记录,我还没有尝试找到精确的边界),那么我会在该表中锁定只要我保持查询打开,SQL Server就可以了。如果我尝试在表上运行更新查询或类似的东西,则会导致死锁。如果我打开一个将此passthrough查询设置为记录源的连续表单,则会发生同样的事情。查看SQL Server中的sys.dm_tran_locks视图显示它是数据页面上的IS锁定...不知道这是否有帮助。只要我点击"最后一条记录" Access中的按钮滚动到查询或表单的末尾,锁定被清除,我的其他进程可以再次更新表格。
据我所知,我的表单和/或查询属性设置为默认值(记录集类型=动态集,记录锁定=无锁)。基于例如动态集的描述。这里给出:https://msdn.microsoft.com/en-us/library/bb188204.aspx 我希望它只需要加载小批量数据来填充可视区域,而无需长时间锁定服务器。正如链接文章所说:
因为它们一次只能使用几行,动态集最小化了 读取锁定在服务器上的持续时间。这允许其他用户 修改数据而不必等待锁定清除所需的时间。
有人可以解释为什么动态集没有按预期行事吗?
我已经看到了几种可能的解决方法,例如
所有这些建议要么对我不起作用,要么似乎有许多其他缺点和/或要求对前端进行重大改写......解决这个问题的最佳方法是什么?
答案 0 :(得分:2)
在深入挖掘并进一步尝试之后,我看到它是这样的:
使用SQL Server上的默认设置,来自Access的动态集确实会保持读锁定,直到它完全加载了所有数据。这对于避免不一致的读取是必要的,否则其他事务可能进入并改变后续"数据包之间的数据顺序。被拉动的动态集,这可能导致重复的行被拉或行被遗漏。 (类似于在查询运行时重建SQL Server页面时NOLOCK查询可能发生的情况)。
所以似乎只有两种方法可以避免它:
1)强制访问"完成"查询,使用快照而不是动态集或通过做某种"最后移动"动态集上的操作,或者确保select语句只返回那些Access将立即加载它们的记录。
2)使用NOLOCK提示或在SQL Server数据库中设置READ_COMMITTED_SNAPSHOT ON来阻止读锁。
我们将使用READ_COMMITTED_SNAPSHOT ON选项,因为它意味着在前端不需要更改任何内容,无论如何我通常不希望在执行读操作时阻止写操作。