MS Access:避免“丢失的更新”

时间:2009-07-24 10:51:10

标签: ms-access transactions jet

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

以下是一些更多细节:

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

什么会导致这种行为?

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

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

感谢您提供任何意见,如果有额外信息需要我知道。

4 个答案:

答案 0 :(得分: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。结果是文件系统复制启动时数据丢失,并且一方面的更改覆盖了另一方的更改。

答案 1 :(得分:0)

继承的MS Access总是最好的,不是吗。为了尽早得到明显的解决方案,我建议将数据移到SQL Server上。这真的不是一件大事。通过将数据库(GUI和数据)拆分为单独的.mdb的

,您也可以获得一些好处

所有人都说过,我以前从未遇到过这种行为。明显的问题是:

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

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

还有一个想法,也许有两个人同时使用写访问权来查看相同的记录;一个人正在记录的不同领域进行更新。

答案 2 :(得分:0)

一些想法:

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

  2. 你说更新后的数据通常会在晚上恢复原状。有人可以运行一个夜间流程,同时更新相同的表吗?

答案 3 :(得分:0)

您对该情景的澄清表示赞赏。

无法实现只读用户可能导致写入用户更改丢失的想法。

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

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

将这些用户级限制应用于表(仅后端,或后端和前端),提供只读管理员用户组和用户用户组,然后给予读/写权限也是明智之举你的一个用户。 Jet ULS与NTFS安全性不同,其中最不允许的权限获胜 - 在Jet ULS中,MOST许可获胜,这就是为什么您必须确保将Admin和User组都设为只读(并且不向Admin提供任何权限)特别是用户,即所有权限都是从组成员身份继承的。)

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

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