代码之家  ›  专栏  ›  技术社区  ›  Thorsten

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

  •  1
  • Thorsten  · 技术社区  · 15 年前

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

    以下是更多详细信息:

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

    什么会导致这种行为?

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

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

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

    4 回复  |  直到 15 年前
        1
  •  0
  •   David-W-Fenton    15 年前

    感谢您对情况的澄清。

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

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

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

    将用户级限制应用于表(仅后端,或后端和前端)也是明智的做法,给予只读的管理用户组和用户用户组,然后给您的一个用户读/写。jet-uls与ntfs安全不同,后者获得的权限最少——在jet-uls中,获得的权限最多,这就是为什么您必须确保管理组和用户组都是只读的(并且不向管理用户特别授予权限,即所有权限都从组成员身份继承)。

    当然,我假设这不是通过后端MDB上的NTFS权限尝试的。如果是这样的话,这很可能是一个大问题,而且根本不是正确的方法。从你所说的来看,这似乎不太可能是正在发生的事情,所以我不再谈论它了。

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

        2
  •  2
  •   David-W-Fenton    15 年前

    十多年前,在发现和修补书签错误之前,我见过一些类似的东西。在这种情况下,通过书签导航留下一个编辑过的记录会在不引发错误的情况下丢失编辑。

    在这种情况下,在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错误处理设置交互。如果为了忽略生成的错误而在下一步错误恢复时代码被乱丢,那么需要完全重写代码。它的问题在于,它并不总是如预期的那样超出范围。

    下一步,我从不使用错误简历。相反,如果我期望某个特定的错误,但又想忽略它,我会捕获该错误并忽略它,从而允许我没有预料到的任何其他错误不会消失在记忆孔中。

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

    另一个需要考虑的问题是后端是否存储在复制驱动器的文件服务器上。对于Access和Jet来说,这是一个不可支持的设置,因为它完全杀死了Jet/Ace的所有记录锁定和内部事务,因为文件图像处于流动状态。我已经看到了关于您描述的两个服务器在哪里被复制的报告,并且正在编辑两个版本的MDB。结果是,当文件系统复制启动并用另一方的更改覆盖一侧的更改时,数据丢失。

        3
  •  0
  •   BIBD    15 年前

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

    都说了,我从来没有遇到过这种行为。显而易见的问题是:

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

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

    还有一个想法,可能有两个具有写访问权限的人同时查看同一个记录;一个是在记录的另一个字段中进行更新。

        4
  •  0
  •   PowerUser    15 年前

    一些想法:

    1. 是否真正需要两个人同时对同一个表具有写访问权限?我认为通过在“工具”->选项中更改“记录锁定”和“打开”模式,您可以轻松地锁定第二个人。

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

    推荐文章