MS Access passthrough选择查询导致SQL Server

时间:2017-02-22 04:11:48

标签: sql-server ms-access sql-server-2008-r2 locking

我正在使用链接到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 我希望它只需要加载小批量数据来填充可视区域,而无需长时间锁定服务器。正如链接文章所说:

  

因为它们一次只能使用几行,动态集最小化了   读取锁定在服务器上的持续时间。这允许其他用户   修改数据而不必等待锁定清除所需的时间。

有人可以解释为什么动态集没有按预期行事吗?

我已经看到了几种可能的解决方法,例如

  • 使用NOLOCK提示(如MS Access holds locks on table rows indefinitely所示,但似乎一般不鼓励NOLOCK?)
  • 使用断开连接的ADO记录集作为我的表单的记录源
  • 将数据从服务器提取到客户端的临时表中,并将表单基于这些临时表
  • 重新设计前端,添加限制器等,以便表格永远不会超过100个记录(如果没有保证它永远不会锁定指定数量的记录,那将是很多工作并且似乎不安全)

所有这些建议要么对我不起作用,要么似乎有许多其他缺点和/或要求对前端进行重大改写......解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

在深入挖掘并进一步尝试之后,我看到它是这样的:

使用SQL Server上的默认设置,来自Access的动态集确实会保持读锁定,直到它完全加载了所有数据。这对于避免不一致的读取是必要的,否则其他事务可能进入并改变后续"数据包之间的数据顺序。被拉动的动态集,这可能导致重复的行被拉或行被遗漏。 (类似于在查询运行时重建SQL Server页面时NOLOCK查询可能发生的情况)。

所以似乎只有两种方法可以避免它:

1)强制访问"完成"查询,使用快照而不是动态集或通过做某种"最后移动"动态集上的操作,或者确保select语句只返回那些Access将立即加载它们的记录。

2)使用NOLOCK提示或在SQL Server数据库中设置READ_COMMITTED_SNAPSHOT ON来阻止读锁。

我们将使用READ_COMMITTED_SNAPSHOT ON选项,因为它意味着在前端不需要更改任何内容,无论如何我通常不希望在执行读操作时阻止写操作。