本节摘要:.accdb 文件内部是一座按"页"组织的仓库:系统表管家底、数据页存货、VBA 工程与窗体定义塞在专门的储藏间;多人共写时靠锁文件 .laccdb 报信、靠事务日志兜底。看懂这套构造,第 3 章的性能经验、第 7 章的运维动作就都有了原理层的解释。
前七章我们一直把 Access 当黑盒用:按钮按下去,数就存进去了。这个盒子关得越久,排障时越心虚——就像开车的人听不见发动机异响。这一节把盖子掀开一角。你不需要成为引擎开发者,但知道了数据放在哪、锁加在哪、断电时靠什么恢复,你在生产现场的每一次判断都会更有底气。
Access 的第一代引擎叫 Jet,1992 年随 Access 1.0 出生,负责解析 SQL、维护索引、执行查询。2007 年,伴随新的 .accdb 格式,微软发布了重写后的引擎并更名 ACE(Access Database Engine)。这次换代加了两样当时很超前的东西——附件字段和多值字段,增强了加密,还内置了 SharePoint 列表通道;但对旧格式 .mdb 的读写能力被完整保留。
| 维度 | Jet 4.0(.mdb 时代) | ACE(.accdb 时代) |
|---|---|---|
| 出场年代 | Access 2000–2003 | Access 2007 至今 |
| 特色字段 | 备注、OLE 对象 | 加附件字段、多值字段、计算字段 |
| 安全模型 | 可选的工作组文件 | 去掉工作组,改用加密与信任中心 |
| 兼容关系 | ACE 向下可读写 | 新特性只在 .accdb 生效 |
给接单人的启示只有一条:新项目一律用 .accdb,除非客户还留着必须在老版本上跑的古董环境。两种格式混用的团队,迟早会在"附件字段怎么读不出来"这种问题上耗掉一个下午——答案很简单,.mdb 里根本没有那个存储结构。
.accdb 采用复合文档的二进制格式组织内容,概念上可以理解成"文件里有个小文件系统"。它至少住着四类住户:
想亲眼确认的话,启用系统对象显示后跑一句:
-- 数一数这个库里到底注册了多少对象、都是什么类型 SELECT MSysObjects.Type, Count(*) AS cnt FROM MSysObjects WHERE Left(Name, 4) <> "MSys" And Left(Name, 1) <> "~" GROUP BY MSysObjects.Type;
类型数字对应表、查询、窗体等不同种类。华彩后端跑出来是五张表九个查询——清单和导航窗格对得上号,说明没有来历不明的孤儿对象。这类"体检式"的小技巧在接手别人做的库时特别好用。

在 DAO 里写下一条更新时,引擎内部发生的事比肉眼可见的多:修改先进缓存,同时把"打算做什么"写进流水记录;事务提交时才正式改写数据页;如果提交前程序崩了或断了电,下次打开库时引擎按流水把未完成的事务撤干净,保证库不会停在半新半旧的中间态。
' 转账式操作:两步要么都成功,要么都不算 Dim ws As DAO.Workspace, db As DAO.Database Set ws = DBEngine(0) Set db = ws.Databases(0) On Error GoTo CleanFail ws.BeginTrans db.Execute "UPDATE tblStock SET Qty = Qty - 2 WHERE ItemID = 105", dbFailOnError db.Execute "INSERT INTO tblShipment (ItemID, Qty) VALUES (105, 2)", dbFailOnError ws.CommitTrans Exit Sub CleanFail: ws.Rollback ' 两步一起作废,库存不会凭空少两件 MsgBox "出库失败已回滚:" & Err.Description, vbExclamation End Sub
注意它的边界:事务只能罩住这一个数据库文件里的表。若你的前端链接了 SQL Server 或另一个 accdb,那些远端表的修改不在这张保护伞里,需要自己在业务层设计补偿逻辑。这是很多"迁移了一半"的系统踩过的暗坑。
理解内幕最好的方式是跟着事故走一遍。华彩上线第三个月的一个早晨,仓管电话说打不开库,报错大意是"文件已被占用"。赶到现场的过程:
顺手解决了第二个隐患:他们此前偶尔出现两人同时改同一段数据时报冲突。检查发现库是以禁用记录级锁定的方式打开的,引擎退化成按整页加锁——同一页上物理相邻的两条无关记录会互相连坐。在选项里勾回"使用记录级锁定打开数据库",冲突频率立刻降下来。页面虽比行大,但相邻记录之间的误伤面小得多;这也是为什么第 2 章建议别把一张大宽表什么都往里塞:行越宽,一页装的行越少,锁的单位反而越粗。
还有一条隐秘的连锁反应值得一提:因为数据页物理相邻存储,频繁删除再插入会让一页里塞满不同批次的碎片记录——这就是为什么高改动的表比只追加的表更需要定期压缩修复。理解了页的存在,连保养节奏都有了物理解释。
本节给出的核心图景三句话:accdb 是分页的复合仓库;多用户的秩序由锁文件与页面锁维系;崩溃一致性靠流水记录兜底。带着这三句话回看前面任何一章的操作建议,你会发现自己已经从"照做"升级到了"知道为什么这么做"。下一节往外看:别的软件怎么进来取数,我们又如何伸手出去。