0

过去的爆炸... 负责管理老化的 Access 2000 adp,用于管理驻留在 SQL 2005 服务器上的数据。在其中一个数据表单上,每当我尝试更改字段并将更改保存回数据库时,它都会在大约一分钟后超时。增加超时限制只会延迟超时错误消息的显示。我经历了所有常见的故障排除以确保兼容性(参见例如这个 SO question)。

这是设置:表单绑定到记录集(作为SELECT * FROM table_name查询从数据库中读取。结果集的大小取决于表单上设置的过滤器,但结果通常约为 200 条记录(不是很多数据...)。表单上的某些字段会触发关联事件处理程序中的自动保存,如下所示:

Private Sub EndDate_Exit(Cancel As Integer)
     some checking goes here...
     ...
     DoCmd.RunCommand acCmdSaveRecord
End Sub

无论何时DoCmd.RunCommand acCmdSaveRecord执行代码,ADP 都会冻结,直到出现超时错误。深入研究它,我查看了 SQL Server 上的活动监视器。acCmdSaveRecord触发一条UPDATE语句返回服务器以保存更改的数据。该语句本身是由 MS Access 根据基础表的主键自动构建的,该主键似乎定义正确。但是,更新被正在运行的SELECT语句阻塞,这与SELECT * FROM table_name上面提到的查询相对应。

这会导致死锁:用户的更改触发了一个UPDATE,它被一个正在运行的程序阻塞SELECT(看起来,它源于正在编辑的表单)。我怎样才能解决这个问题?

我们尝试过的事情:

  1. 我们已删除该DoCmd.RunCommand acCmdSaveRecord语句并将其替换为 code Me.Dirty = False,这会导致与上述完全相同的行为。
  2. 删除了acCmdSaveRecord完整的,并使用内置的访问菜单来保存更改。这是等效于#1 的功能,并导致完全相同的行为。
  3. acCmdSaveRecord调用替换为将更改保存到特定字段的存储过程。效果很好,除了从 GUI 保存整个记录(调用的保存按钮acCmdSaveRecord)会导致相同的死锁。
  4. 将与表单关联的结果集的大小减少到几条记录。奇怪的是,仍然表现出完全相同的行为。
4

1 回答 1

1

听起来好像您已SERIALIZABLE在某个时候为您的连接设置了事务隔离级别。有关详细信息,请参阅SET TRANSACTION ISOLATION LEVEL (Transact-SQL)。这是适用的摘录(已添加重点):

可序列化

指定以下内容:

  • 语句不能读取已被其他事务修改但尚未提交的数据。

  • 在当前事务完成之前,任何其他事务都不能修改当前事务已读取的数据。

  • 在当前事务完成之前,其他事务不能插入键值落在当前事务中的任何语句读取的键范围内的新行。

范围锁被放置在与事务中执行的每个语句的搜索条件相匹配的键值范围内。这会阻止其他事务更新或插入符合当前事务执行的任何语句的任何行。这意味着如果事务中的任何语句第二次执行,它们将读取相同的行集。范围锁一直保持到事务完成。这是隔离级别中最具限制性的,因为它锁定整个范围的键并保持锁定直到事务完成。由于并发性较低,因此仅在必要时使用此选项。此选项与在事务中的所有 SELECT 语句中的所有表上设置 HOLDLOCK 具有相同的效果。

于 2011-11-08T17:21:18.917 回答