为多用户访问设置 MS-Access 数据库

27
我们计划为多个用户创建一些具有多个表、表单和查询的小型MS-Access数据库。(使用不同的后端是另一个长期选择,但目前不可接受。)大多数用户将只读取数据,但会有少量(目前为一到两个)用户需要能够进行更改(当仍有只读用户在使用该数据库时)。我们关心的不是安全方面,而是以下一些问题:
  • 如何确保写入用户可以在其他用户使用数据时更改表格数据?只读用户是否对表格进行锁定?写入用户是否必须对表格进行锁定?Access是为我们执行此操作还是我们必须显式编码?
  • 是否存在与“MS Access交易”相关的常见问题,我们应该注意什么?
  • 在使用表单、查询等时,我们能否同时工作?我们如何“编程”而不妨碍用户?
  • MS Access中哪些设置会影响处理方式?
  • 我们的背景大多在Oracle中,在处理多个用户方面,Access与Oracle有何不同?Access中是否存在“隔离级别”这样的概念?
非常感谢任何有用文章的提示或指针。

当你说“使用不同的后端是另一个...”时,这是否意味着你不想将应用程序拆分为一个后端访问文件和多个访问客户端,还是意味着你不想使用除MS-Access以外的其他解决方案作为后端? - Philippe Grondier
这意味着可以进行拆分,但此时数据必须保留在MS-Access中。 - Thorsten
拆分处理了开发问题,这也是任何有常识的人分发Access应用程序的唯一方法。 - David-W-Fenton
7个回答

53
我发现这个问题的答案有问题、混乱且不完整,所以我会努力做得更好。
Q1:我们如何确保写入用户可以在其他用户使用数据时更改表数据?读取用户是否在表上放置锁定?写入用户是否必须在表上放置锁定?Access是否为我们执行此操作,还是我们必须明确编写代码?
没有人真正完整地回答了这个问题。在Access选项中设置锁定的信息与读取锁定和写入锁定无关。 无锁定、所有记录和编辑记录是您为写入设置默认记录锁定的方式。
- 无锁定意味着您正在使用乐观锁定,这意味着您允许多个用户编辑记录,然后在事后通知他们记录是否已更改。乐观锁定是您应该从中开始的,因为它不需要编写代码即可实现,并且对于小型用户群体几乎永远不会引起问题。 - 所有记录意味着任何时候启动编辑时整个表都被锁定。 - 编辑记录意味着锁定的记录较少,但是是否是单个记录或多个记录取决于您的数据库是否设置为使用记录级锁定(首次添加于Jet 4)或页面级锁定。坦白地说,我从来没有认为设置记录级锁定值得麻烦,因为乐观锁定可以解决大部分问题。
人们可能认为您想使用记录级悲观锁定,但事实是,在绝大多数应用程序中,几乎从不会有两个用户编辑同一条记录。现在,显然,某些类型的应用程序可能是例外,但如果我遇到这样的应用程序,我可能会尝试通过重新设计模式将其消除,以使两个用户很少编辑相同的记录(通常通过转向某种事务性编辑来实现,其中通过添加记录而不是编辑现有数据进行更改)。
现在,针对您的实际问题,有许多方法可以限制某些用户只能读取并授予其他用户写入权限。Jet用户级安全性旨在实现此目的,并且在任何有意义的定义下都可以正常工作。通常情况下,只要您使用Jet/ACE数据存储,您将获得的最佳安全性就是Jet ULS提供的安全性。它是可破解的,但是您的用户如果突破了它,就会犯一个可以被解雇的罪行,所以它可能足够了。
我建议不要使用Jet ULS,而是在设计数据编辑表单时检查用户的Windows登录,并根据需要让表单只读或可写,以便让用户获得相应的访问权限。是否要在数据表中记录组成员身份,或者维护Windows安全组来实现这个目的,取决于您自己。您也可以使用Jet工作组文件来处理它,并为写入用户提供不同的system.mdw文件。只读用户会透明地以管理员身份登录,而以管理员身份登录的用户将只被授予只读访问权限。写用户将使用其他用户名(在您为启动应用程序提供的快捷方式中透明地提供,不提供密码),并用于设置表单为只读或可写。
如果使用Jet ULS,则可能会变得非常麻烦。它涉及将所有表锁定为只读(或甚至不那么严格),然后使用RWOP查询来提供对数据的访问。在我14年的专业Access开发中,我只做了一个这样的应用程序。
总结对您问题的回答:
如何确保写用户可以更改表格数据,而其他用户使用数据?
我建议在应用程序中进行此操作,根据用户登录设置表单在运行时为只读或可编辑。最简单的方法是将表单设置为只读,当编写用户打开表单时将其更改为可编辑。
读用户是否会锁定表格?
没有任何实质性意义。Jet/ACE确实有读锁,但它们仅用于维护单个视图的状态和为用户刷新数据。它们不会锁定任何写操作,尽管理论上跟踪它们的开销会减慢速度。这不足以担忧。
编写用户是否必须对表格进行加锁?
Access与Jet/ACE结合使用可以自动完成此操作,特别是如果您选择乐观锁定作为默认值。关键点在于Access应用程序是数据绑定的,因此一旦加载表单,记录就有一个读锁,并且一旦编辑记录,无论是否为其他用户写入锁定,都取决于您是使用乐观锁定还是悲观锁定。同样,在绑定表单中,Access通过其默认行为为您处理此类事情。直到遇到问题之前,您都不需要担心任何问题。
Access是否为我们完成此操作,还是我们需要显式编写代码?
基本上,除了根据谁具有写访问权限在运行时设置可编辑性之外,如果使用乐观锁定,则不需要编写任何代码。对于悲观锁定,您不必编码,但几乎总是需要的,因为您不能只让用户被困在默认行为和错误消息中。
Q2:使用“MS Access事务”时是否存在任何常见问题需要注意?
Jet/ACE支持提交/回滚事务,但我不确定这是否是您在此问题中的意思。一般来说,除了维护原子性(例如创建发票或涉及多个表的任何更新)之外,我不使用事务。它的工作方式与您预期的大致相同,但在Access应用程序的绝大多数操作中并不是必需的。
也许这里的一个问题(特别是考虑到第一个问题)是您可能没有完全理解Access是为将数据绑定到表单的应用程序而设计的。对于无绑定和无状态的应用程序(例如基于浏览器的应用程序),"事务"是一个非常重要的主题,但对于数据绑定的应用程序,编辑和保存全部是透明的。
对于某些类型的操作,这可能会有问题,偶尔使用无绑定表格在Access中编辑数据是合适的。但在我的经验中,这种情况非常少见。并不是我不使用无绑定表格-我使用很多无绑定表格用于对话框等-只是我的应用程序不使用无绑定表格编辑数据表。几乎没有例外,所有我的应用程序都使用绑定表格编辑数据。
现在,在Access中实际上相当容易实现无绑定表格(特别是如果您将编辑控件命名为底层字段的名称),但使用无绑定数据编辑表格实际上是错过了使用Access的重点,即绑定全部由您完成。而去无绑定的主要缺点是您会失去所有记录级表单事件,例如OnInsert、BeforeUpdate等。
问题3:我们能在使用中处理表单、查询等吗?我们如何“编程”而不妨碍用户?
这是其中一个已经得到很好解决的问题。所有多用户或复制的Access应用程序都应该进行分割,大多数单用户应用程序也应该进行分割。这是良好的设计,也使应用程序更稳定,因为只有数据表才会被多个用户同时打开。
问题4:MS Access中哪些设置会影响处理方式?
“事情?” 什么事?
问题5:我们的背景主要是Oracle,在处理多个用户方面,Access与Oracle有何不同?在Access中是否存在“隔离级别”?
我不知道Oracle的任何具体信息(即使他们想要,我的客户也负担不起它),但要求比较Access和Oracle表明某个地方存在基本的误解。
Access是一个应用程序开发工具。
Oracle是一款工业级数据库服务器。
苹果和橙子。
现在,当然,Access附带默认数据库引擎,最初称为Jet,现在已修订并更名为ACE,但在许多级别上,Access开发平台可以完全与默认数据库引擎Jet/ACE分离。
在这种情况下,您选择使用Jet/ACE后端,对于小用户群体(即少于25人)来说可能会非常好。当只有少数并发用户具有写入权限时,Jet/ACE也可以支持50或100个用户。虽然Jet/ACE中的255个用户限制包括只读和写用户,但真正控制您可以支持多少并发用户的是写用户的数量,在您的情况下,您拥有大多数只读用户的应用程序,因此应该很容易设计一个没有后端问题的好应用程序。
基本上,我认为您的Oracle背景可能会导致您误解如何在Access中开发,其中预期的方法是将表单绑定到记录源,而无需编写代码即可更新。现在,出于效率考虑,最好将表单绑定到记录子集,而不是整个表格,但即使在数据编辑表格的记录源后面有整个表格,只要您的数据表被有效地索引,Access 在编辑Jet/ACE表格方面也会相当高效(关于拉动整个表格跨越线路的旧神话仍然存在)。
记录锁定是您大多数情况下不必担心的事情之一,原因之一是由于绑定编辑,表单始终知道后端正在发生的事情(默认刷新间隔约为1秒)。也就是说,这不像一个网页,您检索数据的副本,然后将您的编辑在事务中发布回到与原始数据检索操作完全无关的服务器上。在像Access这样的绑定环境中,后端数据文件上的锁定文件始终会跟踪记录已打开以供编辑的事实。这可以防止用户的编辑覆盖其他人的编辑,因为Access知道状态并通知用户。这一切都发生在开发人员不需要编写任何代码的情况下,并且是绑定编辑模型的伟大优势之一(除了不必编写代码来发布编辑)。
对于所有有经验的数据库程序员熟悉其他平台的人第一次使用Access,我强烈建议像最终用户一样使用Access。尝试所有点和单击功能。运行表单和报告向导,并查看它们产生的结果。我不能保证所有这些都展示了良好的实践,但它们确实展示了Access旨在使用的默认假设。
如果您发现自己正在编写大量代码,那么您可能会错过Access的要点。

非常有趣且详尽的回答。我并不完全同意你的结论(在UI中实现自己的数据库安全?通过承担相当复杂的时间数据库设计来消除锁定的需求?!!),但仍然做得很好。 - onedaywhen
1
我并没有建议实现“安全性”,而是仅仅提出了用户访问控制,这是完全不同的问题。我提供了所有使用Jet/ACE后端进行此操作的替代方案,并得出结论:一旦你受到限制,你就不会真正寻求真正的安全性(否则你不会选择这种格式),所以我认为主要问题不在于在数据库引擎级别控制写入访问,而是在UI中进行控制。其他人可能会做出不同的评估,但我包括了所有的替代方案。 - David-W-Fenton
1
写入用户是否必须在表上放置锁定?不需要。 - JeffO
任何用户在表上放置读锁,但这并不能防止写入。它只控制读取用户看到的内容(例如,在动态集中)。因此,说写入用户不必在表上放置锁是不正确的(尽管不清楚您是否指的是“记录”或“数据页”,而不是“表”)。 - David-W-Fenton
+1 我是从这个问题http://stackoverflow.com/questions/2007606/from-sql-server-to-ms-access-2007被引导到这里的,我发现你的答案非常有启发性。谢谢 - kristof
+1 对于这个问题,我可能会尝试通过重新设计架构来消除它,使得两个用户同时编辑同一条记录的情况非常罕见。 - NGLN

4
如果还没有这样做,第一件事情是将您的数据库拆分为前端(包含所有的表单/报告等)和后端(包含所有的数据)。第二件事是在前端设置版本控制。我在许多数据库中都是这样做的,即要求用户运行一个小型的“跳板”数据库来打开主数据库。这个跳板会执行以下操作:
• 检查用户是否在他们的C驱动器上有数据库
• 如果没有,则安装和运行
• 如果有,则检查他们使用的版本
• 如果版本号不匹配,则复制最新版本
• 打开数据库
整个检查过程通常不到半秒钟。使用这种模式,您可以在单独的数据库上进行所有开发工作,然后当您准备好“发布”时,只需将新的MDE文件上传到网络共享,并且下次用户打开跳板时,最新版本会被复制下来。
在多用户数据库中也有其他需要考虑的事情,可能值得检查一下常见错误,比如将表单绑定到整个表格等。

在另一条评论中,我已经讨论了分割问题。作为你提到的版本控制的替代方案,请访问 http://www.autofeupdater.com 了解更多关于免费的自动 FE 更新实用工具的信息,以保持每台计算机上的前端最新。一旦设置好了,它可以在开发人员无需进行任何工作的情况下轻松完成更新。 - Tony Toews

2

在Access中,当进行数据写入时可以使用表格或记录锁定。您可以通过“工具”|“选项”|“高级”选项卡来控制默认记录锁定:

  1. 无锁
  2. 所有记录
  3. 已编辑的记录

您可以在表单的记录锁定或特定需要的DAO/ADO代码中设置此选项。

如果正确使用事务,则不应该存在问题。

最佳实践:将数据表与所有其他代码分开。为每个用户提供其自己的代码文件副本,然后在网络服务器上共享数据文件。使用“测试”代码副本(以及指向测试数据文件的链接)进行操作,然后分别更新用户的个人代码文件。如果需要进行数据文件更改(添加表格、列等),则必须让所有用户退出应用程序才能进行更改。

有关Oracle比较,请参见其他答案。


对于分割建议加一,对于锁定评论减一,因此没有赞。 - David-W-Fenton
我认为这个答案并没有帮助,因为它与问题主题无关。问题是只读用户与写入用户之间的区别,这更多是关于使用什么样的默认锁定(乐观或悲观,在表格或页面/记录级别)的问题。对于只有几个用户的人群来说,乐观锁定始终是最好的选择。 - David-W-Fenton
有人直接问了关于表锁定的问题。其他数据库的用户可能会认为Access仅提供写入时的表级锁定,而忽略了记录级锁定的存在。 - JeffO
为什么不编辑您的帖子,以明确这是您打算解决的问题方面。对我来说肯定不清楚,但也许我没有与使用其他数据库的人的误解保持一致。 - David-W-Fenton

2
我认为Access是您情况的最佳选择。但是您需要拆分数据库,请参见: http://accessblog.net/2005/07/how-to-split-database-into-be-and-fe.html •我们如何确保写入用户可以更改表数据,而其他用户使用数据?读取用户是否对表进行锁定?写入用户是否必须对表进行锁定?Access是否会为我们执行此操作,还是我们必须明确编写代码?
除非您明确放置它们,否则没有读锁。只需使用“无锁”。
•使用“MS Access事务”时有哪些常见问题需要注意?
1-2个写入用户不应该有问题。
•当正在使用表单、查询等时,我们能否继续工作?我们如何在不妨碍用户的情况下“编程”?
如果您拆分了数据库,则在FE设计上工作没有问题。
•MS Access中哪些设置会影响处理方式?
您是指哪些方面?
•我们的背景主要是Oracle,在处理多个用户方面,Access与Oracle有何不同?Access中是否存在“隔离级别”这样的东西?
Access中没有隔离级别。 顺便说一句,如果您有大量用户和大型数据库,则稍后可以将数据移动到Oracle并保留Access前端。

1
正确的构建客户端/服务器Microsoft Access应用程序的方法是使用链接表方法,其中数据存储在RDBMS中。这确保了Microsoft Access客户端应用程序和RDBMS数据之间的数据隔离和并发性,而无需额外和不必要的编程逻辑和代码,这使得维护更加困难,并增加了开发时间。
参见:http://claysql.blogspot.com/2014/08/normal-0-false-false-false-en-us-x-none.html

0

Access是一个非常好的多用户数据库。它有很多内置功能来处理多用户情况。事实上,它非常受欢迎,因为它是一个如此出色的多用户数据库。关于同时有多少用户可以使用数据库进行更新和编辑,这取决于开发人员对Access的了解程度以及数据库的设计方式,通常会有一个上限,从20个用户到大约50个用户不等。一些Access数据库可以建立以处理高达50个并发用户,而许多其他数据库可以处理20或25个并发用户更新数据库。这些数字已经观察到用于使用了几年或更长时间的数据库,并且已经在Access新闻组中多次讨论过。


当你说“取决于开发人员对访问和数据库设计的了解程度”时,我们应该注意哪些具体问题? - Thorsten
1
嗯,Christian,也许你应该先学习一下Access和Jet/ACE数据库引擎之间的区别,然后再提出一个有用的问题。 - David-W-Fenton

0

我发现Vista引入的SMB2协议会锁定访问数据库。可以通过以下注册表编辑禁用它:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanServer\Parameters] "Smb2"=dword:00000000


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接