MS Access(MDB)并发
对于一个小项目,我需要使用一个简单的数据库,要求非常简单:几张表,总共不超过几千条logging,2或3个用户。 我在.NET环境中工作。
作为一个数据库服务器(即使那些Express版本)在这种情况下似乎是一个巨大的矫枉过正,一个非常简单的MDB数据库可以满足大多数需求。 然而,我担心并发。 我的想法是将.mdb文件放在networking共享上,并让用户从基于.NET的客户端访问此文件。 数据库主要针对只读操作,但用户偶尔也需要更新/删除logging。 如果在这个时候这是不可能的(由于数据库被locking或者其他原因),我可以在客户端保存更新并在稍后处理。
这个问题本身就是这样的:
- 在MDB中如何处理并发读取?
- 在MDB中如何处理并发更新/删除?
- 有没有锁的概念,我怎么能在.NET应用程序中使用它?
- 将MDB文件放在networking共享上是好还是坏的想法?
当我在.NET中工作时,我也很想知道如何检测任何并发问题并采取适当的措施。 也就是说,我应该抓住哪个例外,你会采取什么行动?
编辑 :这可能是我的问题的不好描述,但大多数的答案似乎build议去一个完整的数据库服务器。 我确实了解安装服务器的差异和好处,实际上在MSSQL和Oracle上实现了相当数量的项目。 但在这个问题上,我只关心Access及其并发问题,所以请不要build议db服务器。
谢谢你的帮助。
这是一个古老的问题,但没有人真正回答过。 以下是问题:
- 在MDB中如何处理并发读取?
- 在MDB中如何处理并发更新/删除?
- 有没有锁的概念,我怎么能在.NET应用程序中使用它?
- 将MDB文件放在networking共享上是好还是坏的想法?
前两个问题基本上可以用一个解释来回答。 一个关键的警告:我在这里给出的答案是特定于Jet MDB(及其变体),并不完全适用于从A2007开始引入的新的文件格式,即ACCDB格式。 我还没有完全探索从ACE中删除Jet ULS的含义,下面的一些评论可能会假定Jet ULS在底层。 不过,对于很多事情,你可以把“LACCDB文件”replace成“LDB文件”,结果是一样的。
1-2)并行读取/更新/删除
Jet数据库引擎通常被称为“文件服务器”数据库,因为没有服务器端恶魔pipe理服务器上数据文件的I / O。 这意味着所有使用Jet MDB的客户端都直接读取文件。
当然,如果没有内置的机制来处理对文件的并发访问,当然就是一个灾难性的秘诀。
Jet使用logginglocking文件,如果您的MDB是“MyFile.MDB”,则logginglocking文件将位于同一文件夹中,并称为“MyFile.LDB”。 LDB文件loggingJet ULS用户打开MDB文件,连接哪个工作站以及协商并发问题所需的所有信息。
现在,对于那些在客户机/服务器数据库引擎上狠下功夫的人来说,这看起来可能是原始的和危险的,但是在开发Jet数据库引擎时,其目的是作为小型工作组的桌面数据库引擎使用,与其他桌面数据库引擎(如xBase和Paradox)竞争,两者都使用类似的locking文件来pipe理来自多个客户端的数据文件的并发使用。
在一个Jet数据库文件中,锁被应用在数据页上(在Jet 4中增加到4K,而在Jet 3.x和之前,它们是2K),或者如果数据表最初创build为使用logging级locking。 在Jet 4的早期,许多人发现logging级别的locking非常缓慢,特别是在使用悲观locking的情况下,所以很多Access开发人员从来不使用任何东西,只是页面级别的locking(@David Fenton举手)。
实际上,在使用乐观locking时,可以避免大多数悲观locking带来的并发问题。
一些注意事项:
-
从DAO,logging级locking不可用,并且您只能获得页面级locking。
-
从DAO中,有许多控制乐观/悲观locking的选项,特别是OpenRecordset方法的LockEdits参数,但是它也与OpenRecordset Options参数中指定的某些设置交互(例如,选项dbReadOnly不能与LockEdits)。 除了locking之外,还可以select一致/不一致的更新,所有这些都可以与事务交互(例如,未完成的事务中的更改不会被其他用户看到,因此不会与它们发生冲突,但它可以在涉及的表上放置只读锁)。
从ADO / OLEDB,这些Jet并发控制结构将被映射到在ADO / OLEDB中find的相关函数和参数。 由于我只从Access使用Jet,因此只能通过DAO与它交互,所以我不能build议如何使用ADO / OLEDB控制这些,但重要的是Jet数据库引擎在访问时提供了对您的logginglocking的控制以编程方式(而不是通过访问用户界面) – 这只是更复杂。
3)锁和.NET
我不能在这里提供任何build议,除了你可能会使用OLEDB作为你的数据接口,但重点是lockingfunction/控制在数据库引擎本身,所以有可能通过控制它的方式OLEDB。 然而,这可能并不美观,因为在我看来,OLEDB是围绕客户机/服务器体系结构devise的,Jet的基于文件的locking可能无法以一种优雅的方式映射到该体系结构上。
4)networking共享上的MDB
Jet对任何networking连接中的最轻微的打嗝都非常敏感。 因此,低带宽networking可能会增加缓慢连接打开的Jet数据库的漏洞。
这是因为数据库文件的主要部分必须通过电线拉到本地计算机的RAM进行处理。 现在,很多人错误地声称整个MDB文件被拉过电线,或者整个表被拉过电线。 这不是真的。 相反,Jet首先请求索引(并请求不超过必要的查询),然后从该结果确定究竟哪些数据页是需要的,然后只拉那些页。 这是惊人的高效和快速。
此外,Jet做了一些非常智能的caching,这可能意味着第一个数据请求可能需要一段时间,但后续的请求相同的数据几乎是瞬间发生的,因为caching。
现在,如果你没有把你的表格编入索引,你最终可能会把整张表格全盘扫描。 同样,如果你在不属于Jet SQL方言的客户端函数的基础上,你最终可能会得到一个完整的表(按照Replace(MyField,“A”,“Z”)sorting可能会导致全表扫描)。 但是这种事情在客户端/服务器体系结构上也会是低效率的,所以这只是常识模式devise,要正确地编制索引,并且要小心使用UDF或非Jet兼容的function。 一般来说,与客户端/服务器效率相同的东西对于Jet来说是有效率的(主要的区别在于,为了避免重新创buildLDB文件的开销,使用Jet你最好使用持久连接,是重要的)。
另一个要避免的是试图通过WiFi连接使用Jet数据。 我们都知道WiFi是多么的不可靠,只是想要通过WiFi连接来处理Jet数据。
底线:
如果您使用MDB作为数据存储来提供来自Web服务器的数据,则应尽可能将数据放在Web服务器的RAM附近。 这意味着在可能的情况下,在连接到物理Web服务器的磁盘卷上。 哪里不可能,你需要一个快速,可靠的局域网连接。 GB数据中心的局域网目前很常见,我很乐意通过这种连接来处理Jet数据。
对于共享使用,例如运行共享单个Jet MDB作为数据存储的VB.NET桌面应用程序的多个客户端工作站,将数据文件放在可靠的文件服务器上是非常安全的。 在可能的情况下,将Jet MDB文件放在不能用于多种用途的计算机上是一个不错的主意(例如,运行Exchange,SQL Server的域控制器,作为文件服务器和打印服务器可能不是最佳位置) 。 像Exchange这样的应用程序可能会严重干扰文件服务器的function,而且我通常build议不要将MDB文件放在多任务服务器上,除非它的体积非常小。
其他考虑:
-
请勿尝试在复制的文件系统上分发MDB,除非所有用户都使用相同的副本。 也就是说,如果你有两台服务器在两台服务器之间复制文件,甚至不要考虑从两台服务器上编辑MDB文件。 这会立即破坏文件。
-
我build议不要将本地Windows文件系统以外的任何MDB存储在本地Microsoft SMBnetworking上。 这意味着没有Novell,没有Linux,没有SAMBA。 这样做的关键原因是,显然从Jet到低级别的lockingfunction,在Windows文件系统中的一些低级别的lockingfunction,没有100%复制在其他文件系统上。 现在,我对此非常保守,很多有能力的Access开发人员都报告了使用正确configuration的Novell文件服务器的出色结果(通常需要进行一些logginglocking调整,尽pipe这些调整可能不太重要,甚至不知道Novell是否还存在!),以及运行SAMBA的基于Linux的文件服务器的性能。 我对此持谨慎态度,并会build议任何客户端使用它(这也包括各种SAN设备,因为不是很多都是基于Windows的)。
-
出于同样的原因,我永远不会在任何虚拟文件系统上运行它们。 不过,我已经有一位客户在Mac Air上使用Parallels下的单用户访问应用程序数年,现在却没有任何问题。 但它是单用户的,所以locking问题将会相对较小。
我不知道这是否回答你的问题。 这一切都基于我作为一个Access开发者和Jet的唯一出版的书,Jet数据库引擎程序员指南(仅适用于Jet 3.5)经常使用的13年的经常使用。 我没有提供任何真正的引用,但是如果有人需要我所说的任何一些细节,我会尽可能地做研究。
多年来,我在Access中build立了十几个小型商业应用程序。 大多数人一次最多有10-20个用户。 数据库分为“应用程序”和“数据”数据库。 性能是体面的,没有问题的一致性。 自从Access 2000 SP2以来,腐败也基本上是不存在的。
有很多人说“永远不要使用Access” – 如果它是正确的(即由一个专业的开发人员),Access是一个相当不错的开发包,我已经很好的生活了。 我的客户对我所build的东西非常满意。
我已经编写了两个使用Access数据库的商业产品,从一个networking共享运行,通常最多10个用户。 如果你不滥用它,那真的没有问题。 但是正如你所看到的,许多开发人员永远都不会到达那里 – 而且由于其低端的特性,在这上面还有许多蹩脚的黑客入侵。 在一个产品的情况下,我必须重新devise应用程序,因为其他人详细描述的所有问题; 但在清理之后,我从来没有在数百个安装中遇到数据库完整性问题。
它的一大优势是单一的文件数据库,这是很容易备份,恢复,并复制到您的笔记本电脑解剖。 几乎所有的select,包括sqlite(尽pipe有些人不会承认它),现在需要某种forms的DBA的关注。
在大多数情况下,Access默认提供logging锁和一些DDL的文件locking(例如模式更改)。
但是微软基本上已经过时了,而且有些同事会对你使用这个软件感到不满。
(在这一点上,我通常鸭子掩护和大叫“进来!!!”)。
访问是真正的桌面单用户解决scheme。 在实践中,它具有“一个”的上限用户限制。
这也是一个本地引擎。 也就是说,当你运行查询时,数据通过networking被拖到本地的JET引擎进行处理。 一个.ldb文件放在networking共享上来控制locking。
如果您使用服务器端引擎(MSSQL,MySQL,Sybase,Orable等),那么您将查询提交给处理它并将结果返回给您的引擎。 锁在内部保存。
这对性能,稳定性和数据完整性有巨大的影响。
如果你的用户决定按下重置button,Access数据库有一个公平的机会损坏,你将不得不删除.ldb。
有了合适的数据库引擎(MSSQL,Sybase,'Orable:我不喜欢MySQL的备份),那么你也是一个适当的备份能力。 除非你有一些虚拟的软件来备份使用文件,否则你可能没有在Access数据库中备份你的数据。
我特别提到了锁,因为数据库引擎可以比任何基于文件的系统更有效和优雅地处理并发和事务。
我可以看到使用Access项目作为数据库引擎的前端,但不能投资于具有Access后端的完整客户端应用程序。
我一直在使用Access,或者更恰当地说,Jet作为一个非常小的私人网站的后端,无法成长,因为它受到这个小国的职业规模的限制。 三年来我没有遇到任何问题。 用户不到一百人,每天大约有三十到四十人使用它。 这些表有几千条logging。
我没有太多的使用经验,但这个链接可能对你有用:
http://office.microsoft.com/en-us/access/HP052408601033.aspx
“你可以把整个Access数据库放在networking服务器上或共享文件夹中,这是最容易实现的方法,每个人都共享数据,并使用相同的表单,报告,查询,macros和模块。希望每个人都以相同的方式使用Access数据库,或者如果您不能支持用户创build自己的对象。
“当您以共享模式打开Access数据库文件(.mdb)时,Microsoft Access还会使用相同的文件名(例如Northwind.ldb)创build一个locking信息文件(.ldb),并与数据库文件位于同一文件夹中。这个locking信息文件存储数据库的每个共享用户的计算机名(如mypc)和安全名(如Admin),Microsoft Access使用这些信息来控制并发性,在大多数情况下,Microsoft Access会自动删除locking信息上次用户closures数据库文件时的文件“。
访问应该是多用户的 – 我认为微软推荐它为多达4或5个用户,但实际上,我build议你不要使用一个以上的单个用户的Access数据库,但如果你真的在没有select的情况下,可以接受两三个,只要有一定的附带条件。
我有4到5个使用Access数据库后端系统的经验 – 所有这些都是从其他“开发人员”那里获得的,在所有情况下,我都将他们作为优先级移动到SQL Server,作为优先级后,立即进行更新和修复当我拿到合同的时候 – 一般我会尽快跟老板交账。 时间跨度通常是几个月,所以我已经看到它在几个不同的应用程序下并行运行一段合理的时间。
实际上,如果系统没有大量的并发插入/更新,并且没有被大量使用,它一般可以很好地工作。 我的经验中的主要实际问题是..
-
这很容易腐败 – 它只是。 通常这不是一个问题,因为打开文件和运行压缩和修复将解决问题,但一个好的备份机制是绝对必要的。
-
这很慢。 每次我将系统升级到SQL Server时,我都收到了很多来自用户加速系统的荣誉。
-
由于Access标记logging被更新或删除的方式,数据库文件膨胀。 由于文件必须通过networking加载,这进一步降低了系统的速度。 因此,通常每天都会压缩数据的一些制度是至关重要的。
所有上述问题都不是单用户系统的问题,因为提示这些问题的根本问题不那么突出。
总而言之,我必须强调,我永远不会build议任何多用户系统的访问。 但是,如果真的有,那么只要它是一个轻微使用的应用程序,并且您执行备份和维护过程,您可能会得到它。
已经多次指出要使用真正的多用户免费数据库平台。 但是其中一个原因尚未说明。 这个原因是,有多less现有的,麻烦的,麻烦的,大型的Access数据库已经开始作为“一些logging,最多一两个用户”? 我敢冒昧地说出他们全部。
除非整个公司只有两三名员工,否则,如果你开发一个有用的软件,它最终将比原来的两三个用户使用更多,比原有的几千条logging并且将在多年内扩展到包括许多表格,更多的表格和更多的数据。 一旦房子build成,你就不能重build房子的基础。 今天build立一个坚实的基础,你可以扩大房子到你心中的内容。 同样的软件。
与networking共享时,我会去与networking启用数据库(MySQL /火鸟/ mssql),而不是访问。
对于你描述使用Access的情况不会是一个问题。
我已经在更具挑战性的情况下使用Access,那么大多数情况下,当访问不被滥用之外,当它与网站一起工作时,这实际上不是一个数据库引擎的坏处。 (不是在谈论forms和东西那样的表格和logging)
当你从多个用户一次插入/更新/删除,然后它有点毛茸茸的。 这是你开始考虑真正的数据库引擎的地步。
另外,当你想要一个线程安全的低开销数据库时,你可以看看vistadb(比访问速度慢,并不总是免费的,100%的.NET)
我认为访问使用表级locking某种排队机制的事情应该工作正常。 如果你担心的话,你可以随时在其上进行模拟压力testing。
我想你可以在.net应用程序连接string中定义它。 我GOOGLE了JET,访问和logginglocking
这里有一个可能有帮助的链接 。
有关Access和JET如何获取数据的真实细节,请参阅接受的答案。
请不要将Access用于多用户场景。
我刚刚经历了两周的痛苦,因为我的一个项目的前任select了Access作为后端。
具体原因:
- Linq-to-Access没有这样的东西
- 访问有许多怪异的依赖关系的顺序添加参数的命令,将需要你年龄的debugging
- 访问不会扩展
- 与使用SQL Server相比,数据库更新是一件苦差事