对于一个小型项目,我需要使用一个非常简单的数据库:少量的表,总共不超过几千个记录,2或3个用户。我在.NET环境中工作。

由于在这种情况下,数据库服务器(甚至包括那些Express版本)似乎是一个过大的矫over过正,因此非常简单的MDB数据库可以满足大多数需求。但是,我担心并发性。我的想法是将.mdb文件放在网络共享上,并允许用户从其基于.NET的客户端访问此文件。该数据库主要针对只读操作,但用户有时也需要更新/删除记录。如果当时无法执行此操作(由于数据库被锁定或其他原因),我可以将更新保存在客户端上,并在以后处理它们。

问题本身遵循以下几点:

  • 在MDB中如何处理并发读取?
  • 如何在MDB中处理并发更新/删除?
  • 有锁的概念吗,如何在.NET应用程序中利用锁?
  • 将MDB文件放在网络共享上是个好主意还是可怕的主意?

  • 当我在.NET中工作时,我也很想知道如何检测并发问题并采取适当的措施。即,我应该捕获哪个异常以及您建议采取什么措施?

    编辑:这可能是我对问题的不好描述,但是大多数答案似乎建议您使用功能完备的数据库服务器。我确实了解安装服务器的区别和好处,并且实际上已经在MSSQL和Oracle上实现了许多项目。但是,在这个问题中,我只关心Access及其并发问题,因此请不要建议使用db服务器。

    谢谢你的帮助。

    最佳答案

    这是一个老问题,但没有人真正回答过。这里是问题:

  • 在MDB中如何处理并发读取?
  • 如何在MDB中处理并发更新/删除?
  • 有锁的概念吗,如何在.NET应用程序中利用锁?
  • 将MDB文件放在网络共享上是个好主意还是可怕的主意?

  • 前两个问题基本上可以用一个解释来回答。这里有一个关键的警告:我在这里给出的答案是特定于Jet MDB(及其变体)的,并不完全适用于从A2007开始引入的新文件格式,即ACCDB格式。我还没有完全探讨过从ACE中删除Jet ULS的含义,下面的一些评论可能认为Jet ULS处于引擎盖之下。但是,对于很多事情,您可以将“LACCDB文件”替换为“LDB文件”,结果将是相同的。
    1-2)并发读取/更新/删除
    Jet数据库引擎通常被称为“文件服务器”数据库,因为没有服务器端守护程序使用服务器上的数据文件来管理I / O。这意味着所有使用Jet MDB的客户端都在直接读取文件。
    如果没有内置用于处理对文件的并发访问的机制,那当然就是灾难的秘诀。
    Jet使用记录锁定文件,如果您的MDB为“MyFile.MDB”,则记录锁定文件将位于同一文件夹中,并称为“MyFile.LDB”。 LDB文件记录哪些Jet ULS用户打开了MDB文件,与该用户连接的工作站以及协商并发问题所需的所有信息。
    现在,对于那些急于使用客户端/服务器数据库引擎的人来说,这似乎是原始且危险的,但是在开发Jet数据库引擎时,其目的是用作小型工作组的桌面数据库引擎,并且与xBase和Paradox等其他桌面数据库引擎竞争,它们都使用类似的锁定文件来管理来自多个客户端的数据文件的并发使用。
    在Jet数据库文件中,锁要么应用于数据页(在Jet 4中增加到4K,而在Jet 3.x及更高版本中则增加到2K),或者如果数据表最初是为创建数据表而在记录级别上应用的。使用记录级锁定。在Jet 4的早期,许多人发现记录级锁定非常慢,尤其是在使用悲观锁定时,因此许多Access开发人员只使用了页面级锁定(@David Fenton举手!)。
    实际上,在使用乐观锁定时,可以避免悲观锁定带来的大多数并发问题。
    一些警告:

    来自DAO的
  • ,记录级别的锁定不可用,并且您只能获得页面级别的锁定。
  • 来自DAO的
  • ,有许多选项可用于控制乐观/悲观锁定,尤其是OpenRecordset方法的LockEdits参数,但它也与OpenRecordset Options参数中指定的某些设置交互(例如,不能使用Option dbReadOnly使用LockEdits)。除了锁定之外,还有用于一致/不一致更新的选项,所有这些更新都可以与事务交互(例如,未提交的事务中的更改对其他用户将不可见,因此不会与它们冲突,但是,可以在所涉及的表上放置只读锁)。

  • 从ADO / OLEDB,这些Jet并发控制结构将被映射到ADO / OLEDB中找到的相关函数和参数。由于我仅从Access使用Jet,因此只能通过DAO与它进行交互,因此我无法建议您如何使用ADO / OLEDB控制它们,但要点是Jet数据库引擎在访问它时提供了对记录锁定的控制以编程方式(而不是通过Access UI)—更加复杂。
    3)锁和.NET
    除了您可能会使用OLEDB作为数据接口(interface)之外,我在这里没有提供任何建议,但关键是数据库引擎本身具有锁定功能/控件,因此很可能有一种方法可以通过OLEDB。但是,这可能不是很漂亮,因为在我看来OLEDB是围绕客户端/服务器体系结构设计的,而Jet的基于文件的锁定可能无法以一种优雅的方式映射到它。
    4)网络共享上的MDB
    Jet对任何网络连接中的轻微故障都非常敏感。因此,低带宽网络可能会增加通过慢速连接打开的Jet数据库的漏洞。
    这是因为数据库文件的主要块必须通过导线拉到本地计算机的RAM进行处理。现在,许多人错误地声称整个MDB文件被拉到网上,或者整个表被拉到网上。这不是真的。相反,Jet首先请求索引(并且只请求完成查询所需的请求),然后从该结果中确切确定需要哪些数据页,然后仅提取那些页。这出奇的高效和快速。
    此外,Jet会执行一些非常智能的缓存,这可能意味着第一个数据请求可能需要一段时间,但是由于缓存,对同一数据的后续请求几乎立即发生。
    现在,如果您对表的索引不够好,您可能最终会拉动整个表并进行全表扫描。同样,如果您将标准基于不属于Jet的SQL方言的客户端函数,则最终可能会提取一个完整的表(例如,对Replace(MyField,“A”,“Z”进行排序)可能会导致全表扫描)。但是,在客户机/服务器体系结构中,这种事情也将是低效的,因此,正确地索引事物并使用UDF或不兼容Jet的功能只是一种常识性的架构设计。通常,对客户机/服务器有效的事情对Jet来说是有效的(主要区别是,对于Jet,您最好使用持久连接,以避免重新创建LDB文件的开销。是重要的)。
    要避免的另一件事是尝试通过WiFi连接使用Jet数据。我们都知道WiFi是不可靠的,只是在尝试通过WiFi连接使用Jet数据时遇到麻烦。
    底线:
    如果将MDB用作数据存储以从Web服务器提供数据,则应将数据尽可能靠近Web服务器的RAM。这意味着在可能的情况下,在连接到物理Web服务器的磁盘卷上。在不可能的地方,您需要快速,可靠的局域网连接。如今,数据中心中的GB LAN很普遍,我很乐意通过这种连接使用Jet数据。
    对于共享使用,例如,运行VB.NET桌面应用程序的多个客户端工作站共享一个Jet MDB作为数据存储,将数据文件存储在可靠的文件服务器上是非常安全的。在可能的情况下,最好将您的Jet MDB文件放在不具有多种用途的计算机上(例如,运行Exchange,SQL Server并充当文件服务器和打印服务器的域 Controller 可能不是最佳位置) 。像Exchange这样的应用程序可能会严重干扰文件服务器功能,因此我通常建议不要将MDB文件放在作为Exchange服务器进行多任务处理的服务器上,除非其体积非常小。
    其他注意事项:

    除非所有用户都使用相同的副本,否则
  • 永远不要尝试在复制的文件系统上分发MDB。也就是说,如果您有两个服务器在它们之间复制文件,那么甚至不要考虑从两个服务器上编辑MDB文件。这将几乎立即损坏文件。
  • 我建议不要将任何MDB存储在通过本地Microsoft SMB网络提供服务的Windows文件系统以外的任何其他文件上。这意味着没有Novell,没有Linux,没有SAMBA。造成这种情况的主要原因是,Jet显然存在Windows文件系统中某些低级锁定功能的底层钩子(Hook),这些钩子(Hook)并未100%复制到其他文件systsm上。现在,我对此非常保守,许多称职的Access开发人员均报告说,使用正确配置的Novell文件服务器可取得出色的效果(通常需要进行一些记录锁定的调整,尽管这些日子可能不那么重要了-我不甚至不知道Novell是否存在!),以及运行SAMBA的基于Linux的文件服务器的出色性能。我对此持谨慎态度,会建议任何客户端反对它(它也包括各种SAN设备,因为其中很多不是基于Windows的)。
  • 出于相同的原因,我永远不会在任何虚拟文件系统上运行它们。但是,我有一个客户已经在Mac Air上的Parallels下运行她的单用户Access应用程序了几年了,没有一个问题。但是它是单用户的,因此锁定问题相对较小。

  • 我不知道这是否回答您的问题。这一切都是基于我13年来经常使用Jet作为Access开发人员,并研究了Jet上唯一的出版书籍《 Jet数据库引擎程序员指南》(仅适用于Jet 3.5)。我没有提供任何真正的引文,但是如果有人需要我所说的内容的详细信息,请尽我所能进行研究。

    关于.net - MS Access(MDB)并发,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/694921/

    10-09 04:53