5.6 KiB
5.6 KiB
PROJ 数据库版本冲突问题修复(2026-03-05)
问题描述
在扫描 D-InSAR 结果时出现 PROJ 错误:
PROJ: proj_identify: C:\Program Files\PostgreSQL\17\share\contrib\postgis-3.6\proj\proj.db
contains DATABASE.LAYOUT.VERSION.MINOR = 2 whereas a number >= 3 is expected.
It comes from another PROJ installation.
根本原因
-
PROJ 版本冲突:
- PostgreSQL 17 自带的 PostGIS 3.6 包含旧版 PROJ 数据库(版本 2)
- GDAL/rasterio 期望 PROJ 数据库版本 >= 3
- 系统在坐标转换时(
Transformer.from_crs)触发此警告
-
环境变量优先级:
- Windows 系统可能将 PostgreSQL 的 PROJ 路径添加到 PATH
- GDAL 默认搜索 PATH 中的 PROJ 数据库
- 找到了 PostgreSQL 的旧版本而非 GDAL 自带的新版本
影响
- 🟡 中等:不会导致程序崩溃,但会产生大量警告日志
- 坐标转换仍然可以工作(PROJ 会回退到兼容模式)
- 日志污染,影响问题排查
解决方案
方案 1:设置 PROJ_LIB 环境变量(已实施)
文件:run_backend.py
修改内容:
def main() -> None:
# Load environment variables
load_dotenv()
# Fix PROJ database version conflict
# PostgreSQL's PROJ database is outdated, use GDAL's bundled PROJ data
# This prevents "DATABASE.LAYOUT.VERSION.MINOR = 2 whereas >= 3 is expected" error
if "PROJ_LIB" not in os.environ:
# Try to find GDAL's PROJ data directory
try:
from osgeo import gdal
gdal_data = gdal.GetConfigOption("GDAL_DATA")
if gdal_data:
proj_lib = os.path.join(os.path.dirname(gdal_data), "proj")
if os.path.exists(proj_lib):
os.environ["PROJ_LIB"] = proj_lib
print(f"[*] Set PROJ_LIB to: {proj_lib}")
except Exception as e:
print(f"[WARN] Could not auto-configure PROJ_LIB: {e}")
port = int(os.getenv("PORT", 8000))
# ... rest of the code
工作原理:
- 在启动时检查
PROJ_LIB环境变量是否已设置 - 如果未设置,尝试从 GDAL 配置中获取 PROJ 数据目录
- 设置
PROJ_LIB指向 GDAL 自带的 PROJ 数据库
方案 2:手动设置环境变量(备选)
如果方案 1 不生效,可以在 .env 文件中手动设置:
# 找到 GDAL 的 PROJ 数据目录
python -c "from osgeo import gdal; import os; print(os.path.join(os.path.dirname(gdal.GetConfigOption('GDAL_DATA')), 'proj'))"
# 将输出路径添加到 .env
PROJ_LIB=C:\path\to\gdal\proj
或者在 PowerShell 启动脚本中设置:
# scripts/start_app.ps1
$env:PROJ_LIB = "C:\path\to\gdal\proj"
方案 3:抑制 GDAL 警告(不推荐)
如果只是想隐藏警告而不解决根本问题:
# 在 run_backend.py 中添加
from osgeo import gdal
gdal.SetConfigOption('CPL_LOG', 'OFF') # 关闭所有 GDAL 日志
不推荐原因:
- 会隐藏所有 GDAL 错误和警告
- 不解决根本问题
- 可能掩盖其他重要错误
验证
1. 检查 PROJ_LIB 是否生效
启动后端后,查看日志:
[*] Set PROJ_LIB to: C:\Users\...\site-packages\osgeo\data\proj
2. 运行扫描任务
在前端触发 D-InSAR 结果扫描,观察日志:
- ✅ 应该不再出现 PROJ 警告
- ✅ Footprint 提取正常完成
3. 验证坐标转换
from pyproj import Transformer
transformer = Transformer.from_crs("EPSG:32650", "EPSG:4326", always_xy=True)
x, y = transformer.transform(500000, 3000000)
print(f"Transformed: {x}, {y}")
# 应该不产生警告
前端锁定问题
问题:扫描任务运行时前端没有锁定
可能原因:
- 扫描任务执行太快(< 3 秒),前端轮询间隔(3 秒)来不及捕获
- 任务状态更新有延迟
解决方案:
方案 A:增加最小锁定时间(推荐)
在扫描任务开始时立即锁定,结束时延迟解锁:
# job_handlers.py
async def _handle_scan_dinsar(job: SystemJobORM) -> None:
if not job.task_id:
raise ValueError("SCAN_DINSAR requires task_id for progress tracking.")
await task_service.start_task(job.task_id, message="正在扫描 D-InSAR 结果...")
# 确保任务至少运行 2 秒,让前端有时间捕获
start_time = time.time()
# ... 执行扫描 ...
# 确保最小执行时间
elapsed = time.time() - start_time
if elapsed < 2.0:
await asyncio.sleep(2.0 - elapsed)
await task_service.complete_task(job.task_id, message="扫描完成")
方案 B:前端立即锁定(更好)
在提交扫描任务后立即锁定前端,不等待轮询:
// DataManagementPanel.jsx
const handleScanDinsarResults = async () => {
try {
// 立即锁定前端
onJobQueued?.(null, 'SCAN_DINSAR');
const response = await scanDinsarResults(selectedDirs);
const taskId = response.data.task_id;
// 更新任务 ID
onJobQueued?.(taskId, 'SCAN_DINSAR');
addLog('info', `D-InSAR 结果扫描任务已提交: ${taskId}`);
} catch (error) {
// 解锁前端
setIsGlobalLocked(false);
addLog('error', `扫描失败: ${error.message}`);
}
};
状态
- ✅ PROJ 环境变量修复已实施
- ⏳ 等待测试验证
- ⏳ 前端锁定问题待确认是否需要修复
下一步
- 重启后端服务
- 运行 D-InSAR 结果扫描
- 观察日志,确认 PROJ 警告消失
- 如果前端仍未锁定,实施方案 B
相关文档
SECURITY_FIX_PROGRESS.md- 安全修复进度HOTFIX_NGINX_BOM_2026-03-04.md- Nginx BOM 修复