diff --git a/h3-console/server.py b/h3-console/server.py index 2756a2b..5c2b30a 100644 --- a/h3-console/server.py +++ b/h3-console/server.py @@ -89,7 +89,16 @@ api = APIRouter(dependencies=[Depends(_require_token)]) # 所有 /v1/* 接口 def db(): - con = sqlite3.connect(DB_PATH) + # 2026-09-05:console 是 8080(LAN)/8081(公网) 两个独立进程共用同一份 sqlite 文件,各自的 + # reconciler_loop 每 5 秒都会对着"进行中的任务"逐条 UPDATE——队列一旦攒到 200+(一次 + # fire-and-forget 式并发提交 150 个任务撞出来的),两个进程的写请求频繁互相撞车。默认 + # journal_mode=DELETE 下同一时刻只允许一个写者、读写还会互相阻塞,且没设 timeout 时 + # sqlite3 的默认等锁时间只有 5 秒,稍微堆一下就直接抛"database is locked",而不是排队 + # 等一下——GET /v1/backends 这种只读查询也会被前面攒着的写请求堵住,实测卡到 38 秒。 + # WAL 模式允许"多个读者 + 一个写者"并发不互斥,配合更长的 busy timeout 让写者互相排队 + # 重试而不是直接报错,两个改动都是连接级别、幂等,不需要额外迁移。 + con = sqlite3.connect(DB_PATH, timeout=30) + con.execute("PRAGMA journal_mode=WAL") con.row_factory = sqlite3.Row return con