Access 数据库的奇怪行为






4.43/5 (11投票s)
我建议所有不知道Microsoft Access MDB文件安全(特别是压缩和修复)的人,在为时已晚之前阅读本文!
引言
不久前,我遇到了一个应用程序中的奇怪行为,该应用程序正在使用Access数据库(*.mdb 文件)。我在CodeProject C++论坛上发了一个问题,但没有得到任何答复。我开始在网上、MSDN等地方搜索……我发现这并非全是我的错。我在一个知识库文章中找到了原因。看看它关于Access数据库文件可能损坏的描述。
"在Access内部和外部,有许多事情可能会导致数据库文件损坏。损坏的数据库的症状可能包括在某些记录中出现#Deleted,或者您无法打开数据库中的某个对象,甚至无法在Access中打开数据库文件。"(MSDN-知识库:283849)
由于我在论坛上没有得到问题的答案,我认为至少有一些人可能不知道这一点,而且由于MDB文件很容易损坏,而要理解应用程序为何运行不正常却很难,所以我开始写这篇文章。
问题是,什么可能导致Access MDB文件损坏,以及如何以编程方式修复损坏的Access文件?
背景
什么可能导致MDB文件损坏
知识库称:
"MDB 文件可能损坏有三个主要原因,如下所示:
- 中断的写入操作
- 有故障的网络硬件
- 在其他程序中打开和保存MDB文件"(MSDN-知识库:283849)
知识库中对其中每一项都有详细的描述,但一些重要的原因如下:
- 数据库写入期间断电
- 网络连接中断
- Microsoft Jet 连接异常终止,例如通过任务管理器强制关闭应用程序、断电、手动关机。(请注意:致命系统错误几乎总是导致异常终止,请参考KB以获取更多信息)
- 忘记关闭打开的ADO或DAO对象(来自类如:Recordset、QueryDef、TableDef和Database的对象)
- 大量的打开和关闭操作在循环中进行(超过40,000次连续的打开和关闭操作可能导致损坏)
- 最糟糕的是,在Microsoft Word等其他程序中**打开**和**保存**MDB文件。这无法恢复。您所有的数据都将丢失。
"在不同的程序中打开并保存的MDB文件无法恢复"
(MSDN-知识库:283849)
如何减少损坏的可能性
- 避免以上所有情况
- 经常压缩数据库(本文提供的类)
情况可能会变得更糟
Q291162:压缩和修复数据库后,自动编号字段重复之前的值:Microsoft还宣布,在压缩和修复数据库后,可能会遇到自动编号字段重复的问题,如果这是您的数据库主键,那么……
幸运的是,这仅适用于使用Microsoft Jet版本4.0.2927.4及更早版本的用户。"Microsoft已确认这是Microsoft Jet版本4.0.2927.4及更早版本中的一个问题。"(Microsoft KB Q291162)。要查找您的Jet引擎版本,请尝试在您的system/32目录中搜索Msjet40.dll(如果您使用的是v.4及更高版本),然后获取文件的属性。此KB可以帮助您找到您的版本并下载最新版本:Q239114。
还存在另一个错误:“压缩Access数据库后,自动编号字段未重置”。我没有对此给出解决方案,因为已经有了,而且它也不是真正关键的问题。有关更多信息,请参考知识库Q287756。
如果您丢失了数据并且在恢复数据时遇到问题(仍然存在),这可以为您提供很大的帮助:Q247771和Q306204。
Using the Code
要使用该代码,请按照以下步骤操作:
- 将DBFitter.cpp和DBFitter.h复制到您的项目中。
- 在DBFitter.cpp中检查并可能更改前两个
#import
指令。#import "D:\PROGRAM FILES\COMMON FILES\System\ado\msado15.dll" rename( "EOF", "MSADO_EOF" ) #import "D:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL" no_namespace
- 包含DBFitter.h,创建一个类型为
DBFitter
的对象,并按如下方式使用它:CDBFitter fitter; if ( !fitter.CompactAndRepair(szDbPath,m_szDBPass) ) { AfxMessageBox(fitter.GetLastErrString()); }
CompactAndRepair
有三种形式可以交替使用。您上面看到的第一种形式,另一种形式只接受数据库文件路径作为输入,并且不使用密码。CompactAndRepair(CString szDbPath)
最后一种形式要求提供源、目标和密码,密码可以为空字符串"",表示没有密码。
CompactAndRepair(CString szSrcDbPath, CString szDstDbPath, CString szDbPassword)
- 别忘了在应用程序的初始化中调用
AfxOleInit();
。
"在运行压缩和修复实用程序之前,请确保以下事项:
在运行数据库的压缩和修复实用程序之前,请确保以下事项:
- 请确保您的硬盘上有足够的可用存储空间来存放Access数据库的原始版本和压缩后的版本。这意味着您必须在该驱动器上拥有至少两倍于Access数据库大小的可用存储空间。如果您需要释放一些空间,请删除该驱动器上任何不需要的文件,或者,如果可能,将Access数据库移动到具有更多可用空间的驱动器上。
- 请确保您对Access数据库具有“打开/运行”和“独占打开”权限。如果您是数据库的所有者,请确保设置这些权限。如果您不是数据库的所有者,请联系其所有者,了解是否可以获得这些权限。
- 请确保没有用户打开了Access数据库。
- 请确保Access数据库未位于只读网络共享上,或者其文件属性未设置为“只读”。"(Q283849)
C# 中的压缩和修复
感谢上帝,已经有一篇文章了。