DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

DuckDB 已设 read_only 仍报 Could not set lock:其他进程仍在读写

Python 已设置 read_only=True,仍可能被另一个读写进程的文件锁挡住。核对所有客户端的打开模式,按只读共享或顺序读写安排任务。

Python 用 duckdb.connect(..., read_only=True) 打开已有文件,仍报 IO Error: Could not set lock on file,并指出另一个 DuckDB CLI、UI 或 Python 进程持有 conflicting lock。此时应检查那个进程如何打开文件,不能只反复给当前连接添加 READ_ONLY。

这里讨论直接打开本地 DuckDB 原生数据库文件的嵌入式客户端。当前文件访问模式允许一个进程读写,或者多个进程全部只读;一个只读客户端不能与另一个直接打开同文件的读写进程自由并存。远程服务协议和 DuckLake 等存储方案有自己的协调机制,不能用它们的能力推断直接文件连接也支持同样的并发。

看持锁进程,也看它的打开方式

保存不含敏感信息的完整错误,核对冲突文件的绝对路径、持锁 PID、客户端版本与启动参数。不要只比文件名:相对路径、符号链接或多个工作目录可能让两份配置实际指向同一个文件。

进程只是查看表,也可能以默认读写模式打开数据库。没有执行 INSERT,不代表没有取得写访问权限。常见情况是先启动带数据库路径的 CLI 或 UI,再运行只读 Python 脚本;后台 Notebook 内核和遗留交互终端也应一起检查。

如果错误明确显示另一个进程持锁,先确认它的任务与负责人。不要直接终止进程或删除数据库、WAL 文件来“解锁”。它可能有未完成事务、正在写入的数据或尚未保存的工作。

如果实际错误是文件不存在、权限不足或同进程连接配置不一致,应按该错误处理;这些现象不能仅凭一句 IO Error 归入跨进程锁冲突。网络共享目录还需要核对文件系统的锁语义,不宜把同一原生文件当作通用共享数据库服务。

只需同时查询时,让所有文件访问都只读

先让原读写任务完成,并正常退出或释放该文件,再按只读方式重新打开。以下是 Python 连接结构示例,路径必须替换成已经存在的目标文件:

import duckdb

con = duckdb.connect("/data/report.duckdb", read_only=True)
try:
    tables = con.execute("SHOW TABLES").fetchall()
finally:
    con.close()

这个参数只控制该连接打开的数据库,不会修改其他进程的访问模式。只读方式不会在路径写错时创建一个新库;连接仍失败时,应继续核对真正的持锁对象,而不是移除参数让空库被自动创建。

CLI、脚本、调度器和可视化工具都必须按各自版本支持的方式只读访问同一个文件。若仍有一处读写连接,其他只读进程仍可能失败。

UI 要保存笔记时,可把数据文件单独只读挂载

UI 自身可能需要写入用于保存笔记的数据库,因此“让整个实例只读”和“把业务文件只读挂载”并不是同一个范围。不要认为给整个 UI 追加 readonly 就一定能正常使用全部功能。

可在支持该方式的版本中,先启动不自动读写打开业务文件的 UI,再在 SQL 界面显式挂载业务库。下面是 SQL 结构示例,别名与路径均需替换:

ATTACH '/data/report.duckdb' AS report_data (READ_ONLY);
SHOW DATABASES;
USE report_data;
SHOW TABLES;

这允许 UI 自身保存所需状态,同时让 report_data 保持只读。前提仍是其他直接打开业务文件的进程也全部只读;它不能解决“UI 只读观察、dbt 同时写同一文件”的需求。

切换写入前,需要先让所有只读访问释放该文件。已挂载且不作为默认数据库的库可以通过对应的 DETACH 释放;默认数据库不能直接 DETACH,应先按当前版本规则切换默认库。Python 中只关闭一个连接句柄也不应直接当作所有模块级实例或其他连接都已释放锁的证明,应核对实际持锁进程和挂载状态。

需要持续写入时,调整工作顺序或访问架构

如果任务是“导入结束后查看”,可以安排写入任务完成并释放文件,再启动只读查看;下一轮写入前先关闭查看端。这会中断查询,应与任务调度共同安排,避免自动重试又把读取进程启动起来。

如果必须持续写入并让多个独立进程读取,评估适合该负载的服务或存储协调方案。不要仅靠应用层定时重试、复制正在写入的文件或移除写锁来模拟支持的并发模型。改用副本或导出快照时,应在一致性得到保证的流程中生成,并明确数据的更新时间。

验收包括下一轮写入

检查所有客户端实际访问的是同一个预期文件,确认同时只读查询可以完成,且业务表与数据没有因路径变动而丢失。不要只用 SELECT 1 判断已经打开了正确数据库。

再按真实调度顺序检查只读查看结束后,原写任务能否重新取得文件;写任务结束后查询能否再次打开。若要回退,先正常释放本次连接或挂载,再恢复原启动参数与任务顺序。仅调整访问方式不应修改业务数据,恢复配置也不等于恢复已被其他任务改变的数据。