MS Access 直通选择查询导致 SQL Server 中的页面锁定
Posted
技术标签:
【中文标题】MS Access 直通选择查询导致 SQL Server 中的页面锁定【英文标题】:MS Access passthrough select query causing page lock in SQL Server 【发布时间】:2017-02-22 04:11:48 【问题描述】:我正在使用链接到 SQL Server 2008 R2 后端的 Access 2007 前端,并且遇到了我认为由简单的直通选择查询引起的奇怪锁定行为。更具体地说:
我有一个简单形式“SELECT * FROM tbl_A”的直通查询。如果我在访问中打开此查询(普通数据表查询视图)并且该表有足够多的记录(大约 > 100 条记录,我还没有尝试找到精确的界限),那么我会在 SQL Server 中锁定该表只要我保持查询打开。如果我尝试在表上运行更新查询或类似的东西,它会导致死锁。如果我打开一个将此传递查询设置为记录源的连续表单,也会发生同样的事情。查看 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 条记录(如果不能保证它永远不会锁定指定数量的记录,这将是大量工作并且看起来不安全)所有这些建议要么对我不起作用,要么似乎有许多其他缺点和/或需要对前端进行重大重写......解决这个问题的最佳方法是什么?
【问题讨论】:
SQL Server 中的基础表是否具有唯一的聚集索引?没有一个可能会引入某些类型的问题,尽管不一定是这个问题。您是否可以选择使用 Access 数据项目?然后你可以使用 OLEDB 代替 ODBC... 您是否尝试过将链接表更改为快照模式?看看这是否会改变行为会很有趣。 感谢 cmets @mroach。是的,该表确实有一个唯一的聚集索引。即使使用纯直通查询(无链接表),我的问题也会出现,我不确定“链接表到快照模式”是什么意思。我尝试将表单“记录集类型”更改为快照,但这并没有改变任何东西。 抱歉,您确实说过您使用的是直通查询而不是链接表。链接表是另一回事。 说实话,我从来没有真正探索过访问数据项目作为一种选择。我们有一个以普通 .accdb 访问权限编写的大型现有应用程序,因此除非绝对必要,否则我会警惕迁移到 adp 可能会扰乱苹果购物车。 Plus adp 在最新的访问版本中不再支持? 【参考方案1】:在四处挖掘和进一步试验之后,我看到它是这样的:
使用 SQL Server 上的默认设置,来自 Access 的动态集确实会保持读取锁定,直到它完全加载所有数据。这对于避免不一致的读取是必要的,否则其他事务可能会进入并更改被拉动的动态集的后续“数据包”之间的数据顺序,这可能导致复制行被拉出或行被丢失。 (类似于在查询运行时重建 SQL Server 页面时 NOLOCK 查询可能发生的情况)。
所以似乎只有两种方法可以避免它:
1) 强制 Access “完成”查询,方法是使用快照而不是动态集,或者对动态集执行某种“移动最后”操作,或者确保 select 语句只返回很少的记录Access 将立即加载它们。
2) 使用 NOLOCK 提示或通过在 SQL Server 数据库中设置 READ_COMMITTED_SNAPSHOT ON 来防止读锁。
我们将使用 READ_COMMITTED_SNAPSHOT ON 选项,因为这意味着无需在前端进行任何更改,而且无论如何我通常不希望在执行读取操作时阻止写入操作。
【讨论】:
以上是关于MS Access 直通选择查询导致 SQL Server 中的页面锁定的主要内容,如果未能解决你的问题,请参考以下文章
MS Access 直通查询 - 使用 ODBC 连接字符串时非常慢,手动选择数据源时速度快 - 问题出在哪里