做 GIS 的人大概都有过这种经历:凌晨一点,相交分析跑到 80% 崩了,弹出一个 ERROR 999999: 执行函数时出错,下面什么都没说。或者图层怎么都删不掉,提示"无法获取方案锁",可你明明已经把所有窗口都关了。这类问题看似玄学,实则背后都有明确的因果链。本文把实际项目中反复验证过的排查经验整理成四个系统分类——999999 报错、锁冲突、桌面端卡顿、服务端性能,每一类都附上成因分析、排查步骤与处置方案对照表,方便快速定位。
一、999999:那个什么都不告诉你的报错
999999 是 ArcGIS 的"兜底错误"——工具内部出了异常但没被正确捕获,于是抛给你一个万能码。官方文档自己也承认这属于异常处理缺失的 bug,所以指望报错信息帮你定位是不现实的,只能按概率排查。按实际处理案例统计,80% 以上的 999999 最终都能归到下面几个原因里,建议按从低成本到高成本的顺序逐项排查。
1. 先看几何
空几何、自相交、短线段、自重叠环——这些脏数据是叠加分析(Intersect、Union、Erase)报 999999 的头号原因。第一步永远是运行修复几何工具:
数据管理工具 → 要素 → 修复几何
在脚本里可以这样写:
arcpy.management.RepairGeometry("input_fc", "DELETE_NULL")
有个细节:如果日志里能看到 TopoEngine 字样,基本可以确定是几何问题。修复完还报错的话,试试多部件转单部件(Multipart to Singlepart),分裂几何引起的问题它能暴露出来。
2. 再看路径和命名
这一条看着低级,但中招的人极多。中文路径、空格、括号、超长目录、输出名以数字开头、用了 SELECT/FROM/GROUP 这类保留字当数据集名——任何一个都可能触发 999999。Esri 官方给的处理建议很直接:输出放到靠近盘符根目录的短英文路径下,比如 D:\work\,别嵌套七八层文件夹。数据放在网络盘上处理也容易被忽略——网络抖一下,读写就失败了。拷到本地盘再跑,很多时候问题自己就消失了。
3. 数据规模
超大要素类或大范围栅格跑着跑着崩掉,往往和内存有关。有效办法是土办法:先裁一小块子集测试,小样本能跑通说明是数据量问题,就分块处理。ArcGIS Pro 里叠加分析有一个更现代的选择——Pairwise 系列工具(成对相交、成对擦除等)。它们用不同的引擎,不走拓扑引擎那条路。Esri 已知问题 BUG-000149002 记录了一个典型案例:输入面大量互相重叠(有的地方叠了近 1500 层)时,标准 Intersect 在拓扑引擎下无解,官方给出的唯一出路就是换 Pairwise Intersect。注意两者输出结果有细微差别,换工具后工作流要核对一下。
4. 环境设置和临时目录
两个环境变量值得在排查时手动设置:
arcpy.env.scratchWorkspace = r"D:\scratch" # 临时工作空间指向本地盘
arcpy.env.parallelProcessingFactor = "0" # 排查期间关掉并行
并行处理因子在个别机器上(尤其核数多但内存紧张的环境)反而是崩溃诱因,先设为 0 排除干扰。另外 C:\Users\xxx\AppData\Local\Temp 里的临时文件堆积过多也会出问题,关掉 Pro 清一次再试。
5. 冷门但致命:坐标域超限
如果错误信息里带着 Coordinate limit exceeded 或 Invalid topology,那不是普通几何问题——是要素类创建时锁定的空间域装不下运算结果生成的新折点。空间域建完就改不了,唯一的办法是新建一个域更大的要素类,把数据拷过去。9.2 之前创建的低精度要素类特别容易犯这个病。
999999 报错排查对照表
| 排查顺序 | 可能原因 | 判断线索 | 处置方案 |
|---|---|---|---|
| 1 | 几何脏数据 | 日志含 TopoEngine;叠加分析崩溃 | 修复几何;多部件转单部件 |
| 2 | 路径或命名不规范 | 中文路径、空格、保留字、网络盘 | 改用短英文本地路径 |
| 3 | 数据规模超限 | 小样本可跑通,全量崩溃 | 分块处理;换 Pairwise 工具 |
| 4 | 环境设置异常 | 并行开启时崩溃;临时目录堆积 | 关并行;清理 Temp;指定 scratchWorkspace |
| 5 | 坐标域超限 | 错误含 Coordinate limit exceeded | 新建更大域要素类并迁移数据 |
一句话总结这节:换到短英文路径的 File GDB → 修复几何 → 统一坐标系 → 小样本测试 → 分块或换 Pairwise。这套组合拳打完,绝大多数 999999 就解决了。
二、锁:删不掉的数据和找不到的进程
文件地理数据库靠 .lock 文件做并发控制,进程访问数据时写入,进程退出时删除。问题出在进程没有正常退出的时候——崩溃、强杀、脚本异常中断,.lock 就留下来了。
先说几个文档里写了但很多人没细看的规则:
- 访问要素数据集里的任何一个要素类,会锁住整个要素数据集;
- 关系类两侧的要素类会一起被锁;
- 地理处理服务每个实例占两个 ArcSOC 进程,其他服务占一个。
所以"我就打开看了一眼怎么就锁了"这种事,在要素数据集里是常态。
僵尸锁怎么处理
先明确一点:残留的 .lock 文件本身不再锁数据,删不删都不影响(它们也不占空间)。真正麻烦的是"活的"锁——某个进程还攥着数据没放。找它别靠猜,用 Sysinternals 的 handle.exe:
handle.exe "D:\data\project.gdb"
输出会列出所有持有该路径句柄的 PID,对着任务管理器杀掉就行。比重启大法体面得多。顺带说两个正经的清理手段:数据库碎片整理(Compact)工具会在压缩过程中移除所有不活动的 .lock;在 Catalog 里复制粘贴地理数据库,也会先清掉源库里的不活动锁。
写 arcpy 的人必看:MakeFeatureLayer 的锁
这是个官方盖章的坑(BUG-000136135,状态是"设计如此,不修"):MakeFeatureLayer 会创建两个引用要素类的对象,锁就下不去。解决办法是显式释放:
res = arcpy.management.MakeFeatureLayer(in_fc, "tmp_lyr")
# ……干完活之后
arcpy.management.Delete(res[0])
del res # 这句不能省
写自动化脚本时养成习惯:用完的 layer 对象 Delete + del,编辑会话用 arcpy.da.Editor 的 with 语法管理。锁冲突十有八九来自代码没显式释放资源。
最后提醒一句:别用 Windows 资源管理器直接复制正在被访问的 .gdb 文件夹。你以为没人用,其实某个进程可能正开着——复制出来的是坏的,而且当时看不出来,过几天访问到某一块才发现数据废了。要复制,走 Catalog。
锁冲突排查对照表
| 场景 | 锁类型 | 典型表现 | 处置方案 |
|---|---|---|---|
| 进程崩溃/强杀/脚本中断 | 残留 .lock 文件 | 不影响数据,但目录里可见 | 无需处理;或 Compact / Catalog 复制清理 |
| 进程仍持有句柄 | 活动锁 | 删数据提示"无法获取方案锁" | handle.exe 定位 PID 后结束进程 |
| arcpy 脚本未释放 | MakeFeatureLayer 锁 | 脚本运行后数据被锁 | Delete + del 显式释放 |
| 要素数据集内访问 | 数据集级锁 | 打开一个要素类,整个数据集被锁 | 理解规则,避免误判 |
三、Pro 卡顿:图层一多就转圈
桌面端性能问题,多数不是机器不行,是地图没配好。按收益从高到低排列如下。
1. 可见比例范围
这是官方文档里反复强调、实践中也最见效的一条。给每个图层(包括标注)设置显示比例,小比例尺下不查数据、不绘制、不发请求。一张图 30 个图层全量显示,和按比例分层显示,流畅度是两个世界。
2. 属性索引
想想你发出去的 where 条件落在哪些字段上——定义查询的字段、Join 的关键字段、符号化用的字段——这些字段都该建索引。一个上百万要素的图层,按未索引字段做定义查询和按索引字段查询,差的不止一个量级。工具:添加属性索引。矢量数据的空间索引在地理数据库里是自动维护的,但做过大批量编辑后重新计算一次,有时能救回查询性能。
3. 坐标系统一
不同空间参考的数据放进同一张地图,会触发动态投影,代价取决于数据量和复杂度。发布要素服务时还会把投影计算压到服务器上,白吃 CPU。建库时就统一坐标系,省掉所有事后麻烦。
4. 大点数据的图格化
点要素类超过几万、几十万个点,启用要素图格(binning),数据源端把点聚合成面块,绘制快得多。哪怕不启用数据源端的 binning,Pro 也能在客户端做聚合。
5. 标注
要素权重(feature weight)设成 None 以外的值,标注引擎要评估每个要素的位置才能放标签,速度断崖式下跌。多标注类的情况用标注摘要报告先定位问题类。
6. 几何瘦身
外部拿来的数据经常带着海量冗余折点——两点之间挤着十几个坐标。简化线/简化面处理一版用于制图显示的副本,原始数据保留全精度,两头都干净。
Pro 卡顿优化对照表
| 优化方向 | 适用场景 | 操作要点 | 预期收益 |
|---|---|---|---|
| 可见比例范围 | 图层多、全量显示 | 为图层和标注设置显示比例 | 极高,减少无效绘制与请求 |
| 属性索引 | 定义查询、Join、符号化字段 | 对关键字段建索引;批量编辑后重算空间索引 | 高,查询速度数量级提升 |
| 坐标系统一 | 多源数据混用 | 建库时统一空间参考 | 高,消除动态投影开销 |
| 要素图格化 | 海量点数据 | 启用数据源端或客户端 binning | 高,绘制性能显著改善 |
| 标注权重 | 标注密集 | 要素权重设 None;用标注摘要报告定位 | 中,避免标注引擎拖慢整体 |
| 几何瘦身 | 外部数据冗余折点多 | 简化线/面生成制图副本 | 中,降低绘制与存储负担 |
四、服务端:发布出去的服务慢
ArcGIS Server 的性能话题说大很大,但抓主要矛盾的话就一件事:ArcSOC 进程的数量和机器资源是否匹配。每个服务实例是一个 ArcSOC.exe 进程,一个实例同时只能处理一个请求。地图和影像服务是 CPU 密集型的,经验规律是:8 核机器上全共享实例的吞吐峰值,大致出现在同时处理 8 个请求的时候。配再多实例,CPU 就那么多,排队等着而已。
1. 共享实例优先,独立实例克制
新部署默认共享实例池,多个服务复用一组 ArcSOC,中位性能和吞吐与独立实例相同,但内存占用显著更低。只有两种情况值得用独立实例:业务上要求某几个服务有更高的优先保障,或者功能上不支持共享(比如非线程安全的 SOE、公共设施网络)。把一大堆服务都设成独立实例,反而会拖累整体性能——共享池可用的资源被你抽走了。
2. 关键服务 min = max
独立实例的最小值小于最大值时,空闲实例会回收,下一个请求进来要等实例冷启动。对性能敏感的核心服务,把最小实例数和最大实例数设成一样,用内存换响应时间。
3. 实例数别瞎拉满
每个 ArcSOC 都要吃一个可用的 vCPU,实例配太多,vCPU 忙的时候全是等待时间;而且每个实例都加载你的数据和 workflow,内存跟着涨。ArcSOC : vCPU 的最优比例没有万能数字,得压测。先用监控工具(ArcGIS Monitor 或系统监视器)看实例利用率和排队情况,再调。
4. 地图服务能缓存就缓存
访问频繁的区域预先切好片,冷门区域用按需缓存补。缓存数据的存放也有讲究:把同一份 File GDB 放到每台 GIS 服务器本地,比放共享网络路径或企业级库快。跑"管理地图服务器缓存切片"之后一定看一眼工具消息——有实例崩掉时,丢失切片的范围会写在消息里,照着补跑就行,别整个重切。
5. 栅格分析的隐藏开关
用 Image Server 做栅格分析的话,有两个默认值值得改:Admin Directory 里把 SOC maximum heap size 从默认 64MB 提到 128MB;在 system properties 里配置 localTempFolder 指向本地快速磁盘,CRF 数据和分布式处理的中间块都会走它,读写速度直接受益。
服务端性能优化对照表
| 优化方向 | 适用场景 | 操作要点 | 预期收益 |
|---|---|---|---|
| 共享实例池 | 多数常规服务 | 保持默认共享实例;避免滥用独立实例 | 高,降低内存占用,维持吞吐 |
| min = max | 核心性能敏感服务 | 独立实例最小值设为最大值 | 中,消除冷启动等待 |
| 实例数调优 | 高并发服务 | 压测后按 vCPU 配比调整 | 高,避免排队与资源浪费 |
| 地图缓存 | 访问频繁的地图服务 | 预切缓存;缓存数据放服务器本地 | 极高,响应速度大幅提升 |
| 栅格分析参数 | Image Server 栅格分析 | heap size 提至 128MB;localTempFolder 指本地快盘 | 中,栅格处理读写加速 |
写在最后
回头看这些年的故障单,其实规律很明显:桌面端的问题十有八九出在数据本身——脏几何、缺索引、坐标系打架;服务端的问题十有八九出在资源配置——实例数拍脑袋、缓存偷懒没做。把这两句话记牢,遇到问题先往这两个方向想,能省掉大量无头苍蝇式的时间。
排查心态上再说一句:999999 和锁冲突这类问题,看起来玄学,其实都有明确的因果链。别信"重启试试",去找那个持有句柄的 PID。
参考资料
- Esri 官方文档:ERROR 999999 错误参考
- Esri 官方文档:文件地理数据库和锁定
- Esri 官方文档:影响数据访问性能的设置、ArcGIS Server 服务调优
- Esri Knowledge Base:BUG-000149002(Intersect 大量重叠数据报 999999)、BUG-000136135(MakeFeatureLayer 锁残留)
- 学术侧如果想系统了解:基于 ArcGIS 的实时态势显控系统设计与性能优化(2010,《计算机工程与设计》)、ArcGIS Server 应用开发中的数据优化策略(2010,《长江科学院院报》)

