Commit 25a489dca4a576eba69a2fb9800f51f6a5858b31
1 parent
96cc2bc2
h3-console: sqlite 开 WAL 模式,修复大批量提交下的 database-is-locked 崩溃
8080(LAN)/8081(公网) 两个进程共用同一份 sqlite,各自的 reconciler_loop 每 5 秒都会对进行中的任务逐条 UPDATE。默认 journal_mode=DELETE 下同一 时刻只允许一个写者、读写还互斥,且没设连接 timeout 时 sqlite3 默认只 等 5 秒——队列一次性堆到 200+(一次 fire-and-forget 并发提交 150 个任务 撞出来的)之后,写请求频繁互相撞车,直接抛 database is locked,连 GET /v1/backends 这种只读查询都被堵到 38 秒才返回。持续了 11+ 小时。 db() 连接加 timeout=30 + PRAGMA journal_mode=WAL,允许多读者+单写者 并发,写者互相排队重试而不是直接报错。部署后 35 秒内 0 次锁错误 (此前几乎每个 reconciler tick 都报错),/v1/backends 恢复到 ~0.3 秒。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFw9ZBh3eVjssk6quYQ4Ki
Showing
1 changed file
with
10 additions
and
1 deletions
h3-console/server.py
| @@ -89,7 +89,16 @@ api = APIRouter(dependencies=[Depends(_require_token)]) # 所有 /v1/* 接口 | @@ -89,7 +89,16 @@ api = APIRouter(dependencies=[Depends(_require_token)]) # 所有 /v1/* 接口 | ||
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | def db(): | 91 | def db(): |
| 92 | - con = sqlite3.connect(DB_PATH) | 92 | + # 2026-09-05:console 是 8080(LAN)/8081(公网) 两个独立进程共用同一份 sqlite 文件,各自的 |
| 93 | + # reconciler_loop 每 5 秒都会对着"进行中的任务"逐条 UPDATE——队列一旦攒到 200+(一次 | ||
| 94 | + # fire-and-forget 式并发提交 150 个任务撞出来的),两个进程的写请求频繁互相撞车。默认 | ||
| 95 | + # journal_mode=DELETE 下同一时刻只允许一个写者、读写还会互相阻塞,且没设 timeout 时 | ||
| 96 | + # sqlite3 的默认等锁时间只有 5 秒,稍微堆一下就直接抛"database is locked",而不是排队 | ||
| 97 | + # 等一下——GET /v1/backends 这种只读查询也会被前面攒着的写请求堵住,实测卡到 38 秒。 | ||
| 98 | + # WAL 模式允许"多个读者 + 一个写者"并发不互斥,配合更长的 busy timeout 让写者互相排队 | ||
| 99 | + # 重试而不是直接报错,两个改动都是连接级别、幂等,不需要额外迁移。 | ||
| 100 | + con = sqlite3.connect(DB_PATH, timeout=30) | ||
| 101 | + con.execute("PRAGMA journal_mode=WAL") | ||
| 93 | con.row_factory = sqlite3.Row | 102 | con.row_factory = sqlite3.Row |
| 94 | return con | 103 | return con |
| 95 | 104 |