对于一个小项目,我需要使用一个要求非常低的简单数据库:几个表,总共不超过几千条记录,2或3个用户.我在.NET环境中工作.
由于数据库服务器(即使是那些Express版本)在这种情况下似乎是一个巨大的过度杀伤,因此非常简单的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文件",结果将是相同的.
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中的相关函数和参数.由于我只使用Jet中的Jet,我只通过DAO与它进行交互,所以我无法建议你如何用ADO/OLEDB控制它们,但关键是Jet数据库引擎在访问它时控制你的记录锁定以编程方式(而不是通过Access UI) - 它更复杂.
我不能在这里提供任何建议,除了你可能使用OLEDB作为你的数据接口,但重点是数据库引擎本身存在锁定功能/控制,所以有可能通过一种方法来控制它OLEDB.但它可能并不漂亮,因为在我看来,OLEDB是围绕客户端/服务器架构设计的,而Jet的基于文件的锁定可能无法以优雅的方式映射到它.
Jet对任何网络连接中最轻微的打嗝非常敏感.因此,低带宽网络可以增加通过慢速连接打开的Jet数据库的漏洞.
这是因为数据库文件的主要块必须通过线路连接到本地计算机的RAM进行处理.现在,许多人错误地声称整个MDB文件都是通过线路拉动的,或者整个表都是通过线路拉动的.这不是真的.相反,Jet首先请求索引(并且请求不超过完成查询所需的请求),然后从该结果确定确切地需要哪些数据页然后仅拉取那些页.这令人惊讶地高效且快速.
此外,Jet执行一些非常智能的缓存,这可能意味着第一个数据请求可能需要一段时间,但由于缓存,后续对相同数据的请求几乎瞬间发生.
现在,如果你没有很好地索引你的表,你可能最终拉出整个表并进行全表扫描.同样,如果您基于客户端函数的标准不是Jet的SQL方言的一部分,您可能最终拉出一个完整的表(排序,比如,替换(MyField,"A","Z")可能会导致全表扫描).但是,对于客户端/服务器体系结构来说,这种事情也会效率低下,所以只需要常识性的模式设计就可以正确地对事物进行索引,并且要小心使用UDF或非Jet兼容的函数.一般来说,与客户端/服务器相关的相同功能对于Jet来说效率很高(主要区别在于使用Jet,您最好使用持久连接,以避免重新创建LDB文件的开销,很重要).
另一件要避免的事情是尝试通过WiFi连接使用Jet数据.我们都知道WiFi是多么不可靠,而且只是在通过WiFi连接尝试使用Jet数据时遇到麻烦.
底线:
如果您使用MDB作为数据存储来从Web服务器提供数据,则应尽可能将数据放在Web服务器的RAM附近.这意味着在可能的情况下,在连接到物理Web服务器的磁盘卷上.如果不可能,您需要快速,可靠的LAN连接.数据中心的GB LAN现在很常见,我很乐意在这种连接中使用Jet数据.
对于共享使用,例如,运行VB.NET桌面应用程序的多个客户端工作站将单个Jet MDB共享为数据存储,将数据文件放在可靠的文件服务器上是非常安全的.在可能的情况下,最好将Jet MDB文件放在不能用于多种用途的计算机上(例如,运行Exchange,SQL Server并充当文件服务器和打印服务器的域控制器可能不是最佳位置) .像Exchange这样的应用程序会严重干扰文件服务器功能,我通常建议永远不要将MDB文件放在多任务服务器上作为Exchange服务器,除非它的容量极低.
其他考虑:
除非所有用户都使用相同的副本,否则永远不要尝试在复制的文件系统上分发MDB.也就是说,如果您有两台服务器在它们之间复制文件,甚至不要考虑从两台服务器编辑MDB文件.这将立即破坏文件.
我建议不要将任何MDB存储在通过本机Microsoft SMB网络提供的本机Windows文件系统之外的任何其他方面.这意味着没有Novell,没有Linux,没有SAMBA.这样做的关键原因是,在Windows文件系统中,Jet显然存在一些低级别锁定,而这些锁定功能并未在其他文件系统上100%复制.现在,我对此非常保守,许多有能力的Access开发人员已经报告了配置正确的Novell文件服务器的优异结果(通常需要进行一些记录锁定调整,尽管这些日子可能不太相关 - 我不喜欢甚至不知道Novell是否还存在!),以及运行SAMBA的基于Linux的文件服务器的卓越性能.我对此很谨慎,并建议任何客户端反对它(这包括各种SAN设备,因为它们中很多都不是基于Windows的).
出于同样的原因,我永远不会在任何虚拟化文件系统上运行它们.但是,我有一个客户在Mac Air上使用Parallels运行她的单用户Access应用程序已有好几年了,现在没有任何问题.但它是单用户,因此锁定问题将相对较小.
我不知道这是否能回答你的问题.这都是基于我13年经常使用Jet作为Access开发人员和研究Jet唯一出版的书籍,Jet数据库引擎程序员指南(仅适用于Jet 3.5).我没有提供任何真正的引用,但如果有人需要我所说的任何事情的细节,我会尽可能做研究.
多年来,我在Access中构建了十几个小型商业应用程序.大多数用户一次最多只有10-20个用户.数据库在"app"和"data"数据库之间分开.性能良好,并没有出现问题.自Access 2000 SP2以来,腐败基本上也不存在.
有很多人说"不要使用Access" - 如果做得对(即专业开发人员),访问是一个非常好的开发包,我已经很好地利用它.我的客户对我的建设非常满意.
我写了两个商业产品,它们使用从网络共享运行的Access数据库,通常最多10个用户.如果你不滥用它,那真的没问题; 但正如你所看到的那样,许多开发人员都没有到达那里 - 而且由于它的低端特性,它上面还有许多糟糕的黑客攻击.在一个产品的情况下,我不得不重新设计应用程序,因为其他人详细描述了所有问题; 但在我清理完之后,我从未在数百个安装中遇到数据库完整性问题.
它的一大优势是单个文件数据库,它易于备份,恢复和复制到您的笔记本电脑进行分析.几乎所有的替代品,包括sqlite(尽管有些人不承认),偶尔需要某种形式的DBA注意.
在大多数情况下,Access默认为一些DDL(例如架构更改)提供记录锁和文件锁.
但微软基本上已经淘汰了它,你的一些同事会嘲笑你使用它.
(在这一点上,我通常会躲避掩护并大喊"收到!!!".)