访问绑定记录集上的 2000 个超时

发布于 2024-12-14 03:10:53 字数 1347 浏览 2 评论 0原文

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

设置如下:表单绑定到记录集(作为 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 语句,并将其替换为代码 Me.Dirty = False,这会导致与上述完全相同的行为。
  2. 完整删除了 acCmdSaveRecord,并使用内置的 Access 菜单保存更改。这是与 #1 等效的功能,并且会导致完全相同的行为。
  3. acCmdSaveRecord 调用替换为将更改保存到特定字段的存储过程。效果很好,除了从 GUI 保存整个记录(调用 acCmdSaveRecord 的保存按钮)会导致相同的死锁。
  4. 将与表单关联的结果集的大小减少到几条记录。奇怪的是,仍然表现出完全相同相同的行为。

Blast from the past... Got tasked to mange an aging Access 2000 adp used to manage data residing on SQL 2005 server. On one of the dataforms, whenever I try to make a change to a field and save the change back to the database, it times out after about a minute. Increasing the time-out limit only delays the display of the time out error message. I went through all the usual troubleshooting to ensure compatibility (see e.g. this SO question).

This is the setup: a Form is bound to a record set (which is read from the database as a SELECT * FROM table_name query. The result set varies in size depending on filters set on the form, but the result is usually around 200 records (not a lot data...). Some of the fields on the form triggers an automatic save in an associated event handler, which looks something like:

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

Whenver the DoCmd.RunCommand acCmdSaveRecord code is executed, the ADP freezes up until I get a timeout error. Digging into it a little deeper, I looked at the Activity Monitor on the SQL Server. The acCmdSaveRecord triggers an UPDATE statement back to the server to save the changed data. The statement itself is automatically constructed by MS Access based on the underlying table's primary key, which appears to be defined correctly. However, the update is blocked by a running SELECT statement, which corresponds to the SELECT * FROM table_name query mentioned above.

This leads to a deadlock: The user's change triggers an UPDATE, which is blocked by a running SELECT (which, as it appears, originated from the Form being edited). How can I get around this?

Things we have tried:

  1. We have removed the DoCmd.RunCommand acCmdSaveRecord statement and replaced it with the code Me.Dirty = False, which leads to the exact same behavior as described above.
  2. Removed the acCmdSaveRecord complete, and used the built-in Access menu to save the change. This is functionality equivalent to #1, and leads to the exact same behavior.
  3. Replace the acCmdSaveRecord call with a stored procedure which saves the change to the specific field. Works great, except that saving the entire record from GUI (save button which calls acCmdSaveRecord) leads to the same deadlock.
  4. Reduced the size of the result set associated with the form to a few records. Oddly, still exhibits the EXACT same behavior.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

土豪 2024-12-21 03:10:53

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

可序列化

指定以下内容:

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

  • 在当前事务完成之前,其他事务都无法修改当前事务已读取的数据。

  • 在当前事务完成之前,其他事务无法插入其键值属于当前事务中任何语句读取的键范围的新行。

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

It sounds as though you have set the transaction isolation level to SERIALIZABLE for your connection at some point. See SET TRANSACTION ISOLATION LEVEL (Transact-SQL) for more details. Here is the applicable excerpt (emphasis added):

SERIALIZABLE

Specifies the following:

  • Statements cannot read data that has been modified but not yet committed by other transactions.

  • No other transactions can modify data that has been read by the current transaction until the current transaction completes.

  • Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.

Range locks are placed in the range of key values that match the search conditions of each statement executed in a transaction. This blocks other transactions from updating or inserting any rows that would qualify for any of the statements executed by the current transaction. This means that if any of the statements in a transaction are executed a second time, they will read the same set of rows. The range locks are held until the transaction completes. This is the most restrictive of the isolation levels because it locks entire ranges of keys and holds the locks until the transaction completes. Because concurrency is lower, use this option only when necessary. This option has the same effect as setting HOLDLOCK on all tables in all SELECT statements in a transaction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文