1

我们继承了一个相当大的 Access DB,它有一些非常奇怪(且令人不安)的行为:对数据库的一些更新丢失了。我们可以做些什么来避免这种情况?Access 中是否有任何设置可以提供更好的事务控制?

以下是更多细节:

  • 我们有一个具有写入权限的访问用户(由非常有限数量的用户共享 - 目前只有我,其他人正在休假)。
  • 我们有另一个访问用户,它被许多人使用,只有读取访问权限。
  • 写入用户对数据进行了一些更改。
  • 离开并重新进入表格和/甚至应用程序后,更改似乎已“提交”。
  • 一段时间后(通常是一夜之间),更改会丢失,数据会恢复到旧值。

什么会导致这种行为?

我们的理论是,这是由 Access 中一些奇怪的事务控制引起的。只读用户对查询或表单中使用的数据获得某种“排他锁”。一旦用户离开该查询/表单,Access 会确保它仍在数据库中。如果同时写入用户更改了数据,这些更改将在只读用户离开查询/表单时恢复,从而导致更新丢失。这有意义吗?这是 MS-Access 的已知问题吗?

此外,我们对如何避免这个问题感兴趣。这是 Access 中固有的东西,只能通过切换到具有更好事务控制的“真实”数据库来避免吗?(从技术角度来看,这很好;但当然,这将是我们在项目的这个阶段宁愿避免的紧急任务。)

感谢您的任何意见,如果需要额外信息,请告诉我。

4

4 回答 4

2

十多年前,在书签错误被发现和修补之前,我已经看到了一些稍微相似的东西。在这种情况下,通过书签导航留下已编辑的记录会丢失编辑而不会引发错误。

在这种情况下,在 MS 对其进行修补之前,解决方案是在离开记录之前强制保存:

  With Me.RecordsetClone
    .FindFirst "..."
    If Not .NoMatch Then
       If Me.Dirty Then
          Me.Dirty = False
       End If
       Me.Bookmark = .Bookmark
    End If
  End With

要检查的另一件事是是否打开了错误报告以及它如何与 VBE 错误处理设置交互。如果代码中到处都是 On Error Resume Next 以忽略生成的错误,则需要完全重写代码。它的问题在于它并不总是像预期的那样超出范围。

我自己从不使用 On Error Resume Next。相反,如果我期待一个特定的错误但想忽略它,我会捕获该错误并忽略它,从而允许我没有预料到的任何其他错误不会消失在内存漏洞中。

我的想法是某种锁定问题正在生成一个被忽略的错误。因此,永远不会报告错误,并且更改会在任何人都不知道的情况下丢失。

要查看的另一件事是后端是否存储在复制驱动器的文件服务器上。对于 Access 和 Jet 来说,这是一个站不住脚的设置,因为它完全杀死了 Jet/ACE 的所有记录锁定和内部事务,因为文件映像处于不断变化的状态。我已经看到关于您所描述的两台服务器被复制的地方的报告,并且 MDB 的两个版本都在被编辑。结果是当文件系统复制启动并用另一侧的更改覆盖一侧的更改时数据丢失。

于 2009-07-24T20:22:41.263 回答
0

感谢您对场景的澄清。

只读用户可能导致写入用户的更改丢失的想法是不可能的。

也许只读用户实际上不是只读的?究竟是如何实现只读与读/写的?在我的应用程序中,我可能会将表单默认设置为只读,并为读/写用户将表单上的 Allowedits/Allowadditions/Allowdeletions 设置为 True。根据您所说的,我假设您正在使用 Jet 用户级安全性,可能默认管理员用户是只读用户,而其他一些用户名是读/写用户。因此,在所有表单中,您都可以在 OnLoad 事件中执行此操作:

  Me.AllowEdits = (CurrentUser()<>"Admin")
  Me.AllowDeletions = Me.AllowEdits
  Me.AllowAdditions = Me.AllowEdits

对表应用用户级别限制(仅后端,或后端和前端)也是明智的,提供只读的管理员用户组和用户用户组,然后为您的一个用户提供读/写. Jet ULS 不像 NTFS 安全性,在 Jet ULS 中,最宽松的权限胜出——在 Jet ULS 中,最宽松的胜出,这就是为什么您必须确保将 Admin 和 User 组都设为只读(并且不授予 Admin 权限特别是用户,即所有权限都继承自组成员身份)。

当然,我假设这不是通过后端 MDB 上的 NTFS 权限来尝试的。如果是这样,那可能是一个主要问题,而且根本不是正确的方法。从你所说的情况来看,这似乎不太可能发生,所以我不会多说。

但是我首先要看的是所谓的只读用户是否真的是只读的。

于 2009-07-26T21:25:07.570 回答
0

一些想法:

  1. 是否真的需要 2 个人同时对同一张表进行写访问?我认为您可以通过更改工具->选项中的记录锁定和打开模式来轻松锁定第二个人。

  2. 你说更新的数据通常会在晚上恢复到原来的状态。有人会在夜间运行同时更新相同表的进程吗?

于 2009-07-24T18:58:26.347 回答
0

继承的 MS Access 总是最好的,不是吗。为了尽早完成显而易见的解决方案,我建议将数据移至 SQL Server。这真的不是什么大工作。您还可以通过将数据库(GUI 和数据)拆分为单独的 .mdb 来获得一些好处

话虽如此,我以前从未遇到过这种行为。明显的问题是:

  • 数据库有多大?
  • 它是什么版本?
  • 它最近是否被压缩和修复(当然先备份)?

您可以使用 MS Access 进行事务处理,但我发现这很麻烦,并且经常导致奇怪的错误(直到您开始了解事务冲突的方式)。您的大多数应用程序可能都假设乐观锁定,并且默认行为与您在 Oracle 或任何其他真实数据库中对事务的看法相矛盾。这可能不值得。

再想一想,也许有两个具有写访问权限的人同时查看同一条记录;一个正在记录的不同字段中进行更新。

于 2009-07-24T14:38:41.873 回答