fix: 盘中脚本统一使用get_conn()替代raw sqlite3.connect防DB死锁

- mofin_health.py, cron_health_monitor.py, intraday_health_check.py,
  self_todo_executor.py: 替换raw sqlite3.connect() → get_conn()
  统一使用WAL模式+busy_timeout=30s连接
- mofin_db.py: get_conn()每次新建连接时WAL checkpoint
  防止被kill进程残留WAL导致后续全部卡死
- 并发测试验证: 3x price_monitor + 3x mofin_health同时运行
  6/6通过,WAL仅32bytes

关联问题: 2026-07-14 SQLite写锁死锁根因诊断
This commit is contained in:
知微
2026-07-14 10:56:38 +08:00
parent 3ee3d9ba6c
commit 59e94d135c
6 changed files with 37 additions and 12 deletions
+2 -2
View File
@@ -255,8 +255,8 @@ def main():
# ── 检查5price_monitor数据新鲜度(直接查DB,不依赖job记录)─
price_key = "price_stale"
try:
import sqlite3
conn = sqlite3.connect("/home/hmo/MoFin/data/mofin.db")
from mofin_db import get_conn
conn = get_conn()
lp = conn.execute("SELECT MAX(updated_at) FROM live_prices").fetchone()[0]
conn.close()
if lp:
+5 -5
View File
@@ -5,9 +5,10 @@
发现问题→写TODO(消费管道与每日体检共享)。
"""
import json, os, sqlite3, subprocess, urllib.request, sys, socket
import json, os, subprocess, urllib.request, sys, socket
from pathlib import Path
from datetime import datetime, timedelta
from mofin_db import get_conn
# ── MoFin path ─────────────────────────────────────────────────────
sys.path.insert(0, "/home/hmo/MoFin")
@@ -56,7 +57,7 @@ def check_http(url, timeout=5):
def db_today_count(table, date_col):
today = datetime.now().strftime("%Y-%m-%d")
try:
conn = sqlite3.connect(str(DB_PATH))
conn = get_conn()
r = conn.execute(f"SELECT COUNT(*) FROM {table} WHERE date({date_col}) = ?", (today,)).fetchone()
conn.close()
return r[0]
@@ -167,7 +168,7 @@ def check_signal_pipeline():
unproc = 0
total_unproc = 0
try:
conn = sqlite3.connect(str(DB_PATH))
conn = get_conn()
# xiaoguo 信号堆积(4h以内时效)
r = conn.execute("SELECT COUNT(*) FROM signal_news WHERE source LIKE 'xiaoguo%' AND (processed=0 OR processed IS NULL) AND created_at > datetime('now', '-4 hours')").fetchone()
unproc = r[0]
@@ -217,8 +218,7 @@ def write_todos():
for msg in ISSUES:
title = f"[盘中自检] {msg}"
try:
conn = sqlite3.connect(str(DB_PATH), timeout=10)
conn.execute("PRAGMA busy_timeout=5000")
conn = get_conn()
# 宏观风险HIGH去重:只要有pending/in_progress的宏观风险TODO,不再新增
if "宏观风险HIGH" in msg:
exist = conn.execute(
+4 -2
View File
@@ -6,9 +6,11 @@
tab2: 数据实体表(输入/输出流分析,孤立表报警)
tab3: 流程/cron映射(状态正常/异常)
"""
import json, sqlite3, os, sys, re
import json, os, sys, re
import sqlite3
from pathlib import Path
from datetime import datetime, timezone
from mofin_db import get_conn
DATA_DIR = Path("/home/hmo/MoFin/data")
WEB_DATA = Path("/home/hmo/web-dashboard/data")
@@ -89,7 +91,7 @@ def load_cron_jobs():
return jobs
def get_db_stats():
conn = sqlite3.connect(str(DATA_DIR / "mofin.db"))
conn = get_conn()
tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").fetchall()
stats = {}
for (tname,) in tables:
+3 -3
View File
@@ -5,9 +5,10 @@
成功→completed。失败→调gateway API,带完整上下文让知微处理。
"""
import json, sqlite3, subprocess, time, urllib.request
import json, subprocess, time, urllib.request
from pathlib import Path
from datetime import datetime
from mofin_db import get_conn
BASE = Path("/home/hmo/MoFin")
DB_PATH = BASE / "data" / "mofin.db"
@@ -28,8 +29,7 @@ def send_xmpp(msg):
def main():
start = time.time()
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
conn = get_conn()
rows = conn.execute(
"SELECT id, title, description, fix_action FROM todos WHERE status='pending' "