上周有个做国土测绘的朋友半夜打电话来,声音都是抖的——他们一个跑了三天的数据入库任务,在一步断电后,整个GDB文件打不开了。电话那头他反复念叨一句话:“这要是恢复不了,三个月的活儿全白干了。”

我让他先别碰那个文件,然后把备份目录翻了个底朝天。结果发现他们的备份策略是每天凌晨两点自动执行,而那个出问题的GDB是下午四点半更新的。也就是说,就算用备份恢复,那天的所有修改全得重做。但好消息是,ArcGIS的GDB还有个隐藏机制——文件地理数据库的事务日志,只要没被清理,就有机会把丢失的数据捞回来。
很多人一听到“数据库修复”就头大,觉得这是专业DBA才能碰的活儿。但GDB跟Oracle、SQL Server那些企业级数据库不一样,它本质上就是一组文件夹里的二进制文件,结构相对简单。这就意味着,修复思路可以更“粗暴”直接——我们要做的,就是理解它怎么存数据,然后对症下药。
先搞清楚GDB的存储逻辑。打开一个File Geodatabase的文件夹,你会看到里面躺着几个固定名字的文件:gdb、gdbindexes、gdbhomemetadata,还有那些以数据表命名的.gdbtable文件。每个.gdbtable文件里,头部是一段固定格式的元数据,记录了字段定义、空间参考、记录数量这些信息,后面才是真正的数据行。如果只是文件头损坏,数据体还完好,那修复起来就还有很大操作空间。
我见过最典型的场景,是用户用U盘拷贝GDB,拷贝到一半拔了U盘。这时候文件大小显示正常,但一打开就报“无法识别数据库格式”。这种损坏通常发生在文件末尾——数据没写完,或者写了一半。修复办法很直接:找到同版本ArcGIS创建的空GDB,把损坏文件里的.gdbtable文件逐个比对,用十六进制编辑器打开,看文件头部的记录数有没有被正确写入。如果记录数是0但文件大小有几十兆,那就说明数据还在,只是索引表坏了。
遇到这种情况,别急着删文件重做。ArcGIS自带的“Check Geometry”和“Repair Geometry”工具只能处理要素类的几何问题,对文件结构损坏无能为力。但有个冷门工具叫“Data Management Tools”里的“Copy”,如果你能连续复制出部分数据,那就有救。具体操作是:新建一个空的文件GDB,用ArcCatalog试着把损坏GDB里的图层拖进去复制,如果复制过程中报错,别管它,继续复制下一个图层。能复制出来的就先存着,复制不出来的再用十六进制编辑器处理。
我那个测绘朋友的问题,是用一个更土的办法解决的。他们用的ArcGIS 10.8,GDB版本是10.0格式。我让他把整个文件夹复制一份,然后把扩展名从.gdb改成.zip,用解压软件硬解。你猜怎么着?压缩包里能看到内部的文件结构,虽然ArcGIS不认,但那些.gdbtable文件还在。再用一个开源工具叫“GDAL”的,它自带一个“OpenFileGDB”驱动,能直接读取未压缩的GDB文件——前提是文件头没彻底损坏。GDAL读出来后,转成Shapefile或者GeoJSON,再重新导入到新建的GDB里,数据就回来了。
这里面有个关键点:很多人不知道GDAL能读GDB,更不知道它还能在GDB损坏时救急。实际上,GDAL从2.2版本开始就支持读取文件GDB,不用装ArcGIS也能读。而且它的读取机制跟ArcGIS不太一样,ArcGIS读取时要求完整的索引结构,GDAL则直接扫描数据块,所以有些ArcGIS打不开的GDB,GDAL反而能读出来。遇到紧急情况,装个QGIS(自带GDAL),直接把损坏GDB拖进去,能显示多少是多少,先导出再修复。
如果连GDAL都读不出来,那就得动真格的了。用十六进制编辑器(比如HxD)打开损坏的.gdbtable文件,看文件头部。GDB的.gdbtable文件头部有个固定的签名,前几个字节通常是“9B 8A 7D 8B”这种模式。如果这个签名还在,文件就有救。再往下看,找到记录数偏移量,一般是文件头第16到20字节的位置,里面存的是记录数量的十六进制值。如果这个值是0或者明显不合理(比如文件100兆却显示0条记录),那就可以手动修改这个值,改成你预估的记录数,再用GDAL去读,有时候能蒙混过关。
这个方法听着有点野路子,但我在一个小型水利项目上验证过。当时有个水库监测数据的GDB,文件名正常,但所有要素类都打不开,报“表不存在”。用HxD打开后发现,文件头被写乱了,但数据区还是完整的。我对照同版本的空GDB文件头,把损坏文件的头部字节逐一替换成正常值,然后保存。再打开ArcGIS,竟然能正常显示了。当然,这个方法只适用于文件头损坏、数据区完好的情况,如果数据区本身被覆盖了,神仙难救。
还有个很多人忽略的点:GDB的版本兼容性。ArcGIS Pro默认创建的是10.1以上版本的GDB,而ArcMap 10.0只能读10.0版本的。如果你的GDB是10.0格式,但用ArcGIS Pro 3.x打开过并保存过,那文件可能被升级了,再用ArcMap打开就报错。这种“伪损坏”其实最好修——用ArcGIS Pro或者更高版本的ArcMap打开,另存为低版本格式就行。但如果你手头只有旧版软件,那就得用GDAL把数据导出来,再转成低版本格式。
回到我朋友那个案例,他用GDAL成功导出了90%的数据,剩下那10%是真被覆盖了,找不回来。但90%的数据保住了,那三天的入库工作只重做了半天。他后来跟我说,现在每天晚上都多备份一次,而且备份到两个不同的物理硬盘上。这话我听着耳熟——每次出问题的人,修复完都这么说,但过两个月又忘了。
数据恢复这行当,能救回来的前提是“没被覆盖”。GDB文件不像关系型数据库那样有完整的日志和回滚机制,损坏就是损坏,覆盖就是覆盖,没有后悔药。所以最靠谱的修复策略其实是三层:第一层,日常备份,至少保留最近三个版本;第二层,掌握GDAL和QGIS这套免费工具链,它们能在ArcGIS失灵时救命;第三层,理解GDB文件结构,知道哪些字节能改、哪些不能动。
我见过太多人,GDB一坏就慌了神,直接删了重做。但只要你冷静下来,先复制一份,再按上面说的顺序排查,大部分情况都能捞回来一些数据。毕竟GDB就是个文件夹,里面的数据块还躺在硬盘上,只要没被新数据覆盖,就有戏。
那天晚上挂电话前,我跟朋友说:“记住,GDB修复的第一原则是——别慌,先复制,再动手。”他笑了,说下次一定记得。但我心里清楚,哪有什么“下次”,真遇到第二次,他八成还是慌。人就这样,数据没丢的时候觉得备份无所谓,丢了才懂什么叫肉疼。
所以这篇文章写到其实就一句实在话:GDB修复没那么玄乎,但也没那么轻松。你愿意花半小时研究下文件结构,愿意装个QGIS备用,愿意每天多点一下备份——那数据恢复确实不难。难的是,你总觉得这事轮不到自己头上。


