MS Access (MDB) 并发

2023-12-02

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

由于数据库服务器(即使是那些 Express 版本)在这种情况下似乎是一个巨大的杀伤力,一个非常简单的 MDB 数据库可以满足大多数要求。然而,我担心并发性。我的想法是将 .mdb 文件放在网络共享上,并让用户从基于 .NET 的客户端访问该文件。数据库主要针对只读操作,但用户偶尔也需要更新/删除记录。如果当时无法做到这一点(由于数据库被锁定或其他原因),我可以在客户端上保留更新并稍后处理它们。

问题本身遵循以下几点:

  • MDB 中如何处理并发读取?
  • MDB 中如何处理并发更新/删除?
  • 是否存在锁的概念以及如何在 .NET 应用程序中利用它?
  • 将 MDB 文件放在网络共享上是好主意还是坏主意?

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

EDIT:这可能是我对问题的错误描述,但大多数答案似乎建议使用成熟的数据库服务器。我确实了解服务器安装的差异和好处,并且实际上已经在 MSSQL 和 Oracle 上实施了相当多的项目。然而,在这个问题中,我只关心 Access 及其并发问题,所以请不要建议数据库服务器。

感谢您的帮助。


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

  1. MDB 中如何处理并发读取?
  2. MDB 中如何处理并发更新/删除?
  3. 是否存在锁的概念以及如何在 .NET 应用程序中利用它?
  4. 将 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 举手!)。

事实上,使用乐观锁定时,您可以避免悲观锁定带来的大多数并发问题。

一些注意事项:

  1. 从 DAO 中,记录级锁定不可用,您只能获得页级锁定。

  2. 从 DAO 中,有许多用于控制乐观/悲观锁定的选项,特别是 OpenRecordset 方法的 LockEdits 参数,但它也会与 OpenRecordset Options 参数中指定的某些设置交互(例如,选项 dbReadOnly 不能与锁定编辑)。除了锁定之外,还有一致/不一致更新的选项,所有这些都可以与事务交互(例如,未提交事务中的更改不会对其他用户可见,因此不会与他们冲突,但它可以在涉及的表上放置只读锁)。

从 ADO/OLEDB 中,这些 Jet 并发控制结构将映射到 ADO/OLEDB 中的相关函数和参数。由于我仅从 Access 使用 Jet,因此仅通过 DAO 与其交互,因此我无法建议您如何使用 ADO/OLEDB 控制这些,但重点是 Jet 数据库引擎在访问它时提供对记录锁定的控制以编程方式(而不是通过 Access UI)——只是更复杂。

3) 锁和.NET

我不能在这里提供任何建议,除了您可能会使用 OLEDB 作为数据接口之外,但关键是锁定功能/控制位于数据库引擎本身中,因此可能有一种方法可以通过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 服务器的磁盘卷上。如果无法做到这一点,您需要快速、可靠的 LAN 连接。如今,数据中心中的 GB LAN 非常常见,我非常乐意通过这种连接使用 Jet 数据。

对于共享使用,例如,运行共享单个 Jet MDB 作为数据存储的 VB.NET 桌面应用程序的多个客户端工作站,将数据文件放在可靠的文件服务器上是非常安全的。如果可能,最好将 Jet MDB 文件放在不具有多种用途的计算机上(例如,运行 Exchange、SQL Server 并充当文件服务器和打印服务器的域控制器可能不是最佳位置) 。像 Exchange 这样的应用程序可能会严重干扰文件服务器功能,我通常建议永远不要将 MDB 文件放在像 Exchange 服务器一样进行多任务处理的服务器上,除非它的容量极低。

其他考虑因素:

  1. 切勿尝试在复制的文件系统上分发 MDB,除非所有用户都使用相同的副本。也就是说,如果您有两台服务器在它们之间复制文件,则无需考虑从两台服务器编辑 MDB 文件。这几乎会立即损坏文件。

  2. 我建议不要将任何 MDB 存储在除通过本机 Microsoft SMB 网络提供服务的本机 Windows 文件系统之外的任何其他设备上。这意味着没有 Novell、没有 Linux、没有 SAMBA。造成这种情况的关键原因是,Jet 显然对 Windows 文件系统中的某些低级锁定功能进行了低级挂钩,而这些功能并未 100% 复制到其他文件系统上。现在,我对此非常保守,许多有能力的 Access 开发人员都报告了正确配置的 Novell 文件服务器的出色结果(通常需要进行一些记录锁定调整,尽管现在可能不太相关 - 我不知道)甚至不知道 Novell 是否还存在!),以及运行 SAMBA 的基于 Linux 的文件服务器的惊人性能。我对此持谨慎态度,并建议任何客户端不要使用它(这也包括各种 SAN 设备,因为其中不是很多都是基于 Windows 的)。

  3. 出于同样的原因,我永远不会在任何虚拟化文件系统上运行它们。不过,我有一位客户,她已经在 Mac Air 上的 Parallels 下运行她的单用户 Access 应用程序好几年了,没有出现任何问题。但它是单用户的,因此锁定问题相对较小。

我不知道这是否能回答你的问题。这一切都是基于我作为 Access 开发人员 13 年来定期使用 Jet 以及对有关 Jet 的唯一出版书籍《Jet 数据库引擎程序员指南》(仅适用于 Jet 3.5)的研究。我没有提供任何真实的引文,但如果有人需要我所说的任何细节,我会尽可能进行研究。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MS Access (MDB) 并发 的相关文章

  • MS Access 中重命名列的 DDL 是什么?

    在 MS Access 中重命名列的 DDL 是什么 大致如下 alter table myTable rename col1 to col2 它不适用于 MSAccess 2000 格式的数据库 我正在将 OLEDB 或 ADO NET
  • 计算按月分隔的两个日期之间的天数

    我需要计算两个日期之间的天数 DateTime 但有一个转折 我想知道这两天跨越的每个月有多少天 两个人有简单的方法吗 Example 我的开始日期是 30 03 2011 结束日期是 05 04 2011 那么结果应该是这样的 var r
  • 为什么我的 COM 对象不显示组件服务中的方法?

    我正在尝试创建一个 COM 对象并将其注册到 COM 下 一切似乎都很顺利 但是当我查看组件服务并深入了解时 控制台根目录 组件服务 电脑 我的电脑 COM 应用程序 测试通讯 组件 TestCom Com MyCom 接口 MyCom 方
  • IL 的仿制药?

    是否可以在 IL 生成器中使用泛型 DynamicMethod method new DynamicMethod GetStuff typeof int new Type typeof object ILGenerator il metho
  • 正则表达式不等于字符串

    我用正则表达式用头撞墙 我正在尝试定义一个表达式 该表达式完全排除此文本 System 不区分大小写 但可以包含 系统 这个词提供的不仅仅是这个 例子 系统 无效 系统 无效 系统 无效 系统 无效 asd 系统 有效 asd 系统 asd
  • 分层架构中的异常处理

    我们正在分层设计中重构 当然还有重新设计 我们的服务 我们有服务操作层 BLL 网络抽象层 gt 处理网络代理 数据抽象层 但我们对我们的异常处理策略有点困惑 我们不想向外界透露太多 BLL 的信息 从其他层到bll就可以了 我们不想让 t
  • ThreadPoolExecutor 和队列

    我以为使用线程池执行器 http docs oracle com javase 6 docs api java util concurrent ThreadPoolExecutor html我们可以提交Runnables 要在以下位置执行B
  • 使用 MS Access 获取行的第一个实例

    EDITED 我有这个查询 我想SELECT表中记录的第一个实例petTable SELECT id pet ID FIRST petName First Description FROM petTable GROUP BY pet ID
  • 实用程序库中应包含哪些内容[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 随着我的项目越来越多 我发现我经常从一个项目到另一个项目 从一个客户到另一个客户重复许多常见的任务 因此 我开始组装一个 实用程序 库 这是这些
  • ASP.NET MVC 中 ModelState.AddModelError 中的关键参数有什么意义?

    我在我的控制器中添加了验证检查来修改ModelState如果验证失败 例如 private bool ValidateMoney string raw string name decimal min decimal max try var
  • 找不到 Microsoft.Office.Interop Visual Studio

    我正在开发一个使用 C 发送电子邮件的应用程序 该应用程序将能够使用邮件模板等 问题是我无法找到任何 Office Interop 引用 这意味着我无法使用 Outlook 我的计算机上安装了 Office 但我也尝试从此链接安装 PIAh
  • 在 .Net 托管的 IronPython 脚本中设置和获取变量

    我正在尝试使用 Net 控制台应用程序中托管的 IronPython 来构建验证规则引擎的原型 我已经将脚本精简到我认为的基础内容 var engine Python CreateEngine engine Execute from Sys
  • 如何在 Visual Studio 中更改 Azure 数据库表的列顺序

    我整个下午都在寻找在 MS Visual Studio 2022 中重新排序 Azure 数据库表列的方法 没有运气 在其他应用程序中 可以通过拖动或剪切和粘贴轻松重新排列列 这里无能为力 此时 我什至不确定可以在 VS 中移动列 我只对
  • 在 C# 中使用通配符解析相对路径

    在 C 中 如果我有一个目录路径和一个带通配符的相对文件路径 例如 c foo bar and blah cpp 有没有一种简单的方法来获取绝对文件路径列表 例如 c foo blah a cpp c foo blah b cpp 背景 有
  • 调整图像的亮度、对比度和伽玛值

    在 NET 中调整图像的亮度 对比度和伽玛值的简单方法是什么 c and gdi have a simple way to control the colors that are drawn It s basically a ColorMa
  • 如何正确转义mysql?

    我刚刚发现如果我写 select from tbl where name like foo 然后添加 foo 作为参数及其值 a 用户数据 它不会正确转义 我勒个去 它想要 a 即使我使用参数 我还是忍不住觉得我对 sql 注入持开放态度
  • 将古吉拉特语文本插入 MySQL 表会产生垃圾字符和不可读的文本

    我有三个 MySQL 表 我正在向其中插入古吉拉特语内容 当我插入两个表时 它们插入得很好并且可读 但在一个表中 它显示垃圾字符 不可读的文本 我怎样才能解决这个问题 MySQL 有每个表的字符集设置 http dev mysql com
  • VB.NET 中的静态方法实现

    我很困惑Static在 VB NET 中的实现 在 C 中 我们可以创建静态类和静态方法来为我们的应用程序编写实用方法 现在 VB NET 让我们创建Module代替静态类 如果我们在模块中创建一个方法 默认情况下它会变成静态的 但在我的应
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org

随机推荐