perf(db): tune sqlite pool and add maintenance scheduler
This commit is contained in:
@@ -29,6 +29,12 @@ config = get_config()
|
||||
USER_ACCOUNTS_EXPIRE_SECONDS = int(getattr(config, "USER_ACCOUNTS_EXPIRE_SECONDS", 3600))
|
||||
BATCH_TASK_EXPIRE_SECONDS = int(getattr(config, "BATCH_TASK_EXPIRE_SECONDS", 21600))
|
||||
PENDING_RANDOM_EXPIRE_SECONDS = int(getattr(config, "PENDING_RANDOM_EXPIRE_SECONDS", 7200))
|
||||
DB_PRAGMA_OPTIMIZE_INTERVAL_SECONDS = max(300, int(getattr(config, "DB_PRAGMA_OPTIMIZE_INTERVAL_SECONDS", 21600)))
|
||||
DB_ANALYZE_INTERVAL_SECONDS = max(0, int(getattr(config, "DB_ANALYZE_INTERVAL_SECONDS", 86400)))
|
||||
DB_WAL_CHECKPOINT_INTERVAL_SECONDS = max(0, int(getattr(config, "DB_WAL_CHECKPOINT_INTERVAL_SECONDS", 43200)))
|
||||
DB_WAL_CHECKPOINT_MODE = str(getattr(config, "DB_WAL_CHECKPOINT_MODE", "PASSIVE") or "PASSIVE").upper().strip()
|
||||
if DB_WAL_CHECKPOINT_MODE not in {"PASSIVE", "FULL", "RESTART", "TRUNCATE"}:
|
||||
DB_WAL_CHECKPOINT_MODE = "PASSIVE"
|
||||
|
||||
# 金山文档离线通知状态:每次掉线只通知一次,恢复在线后重置
|
||||
_kdocs_offline_notified: bool = False
|
||||
@@ -275,6 +281,80 @@ def start_cleanup_scheduler() -> None:
|
||||
logger.info("内存清理调度器已启动")
|
||||
|
||||
|
||||
def _execute_db_statement(statement: str, *, commit: bool = False, fetchone: bool = False):
|
||||
import db_pool
|
||||
|
||||
with db_pool.get_db() as conn:
|
||||
conn.execute(statement)
|
||||
row = conn.fetchone() if fetchone else None
|
||||
if commit:
|
||||
conn.commit()
|
||||
return row
|
||||
|
||||
|
||||
def optimize_database_runtime() -> None:
|
||||
"""执行 SQLite 运行期优化,提升查询计划和页缓存命中率。"""
|
||||
row = _execute_db_statement("PRAGMA optimize", fetchone=True)
|
||||
if row:
|
||||
logger.debug(f"[DB维护] PRAGMA optimize 已执行: {tuple(row)}")
|
||||
else:
|
||||
logger.debug("[DB维护] PRAGMA optimize 已执行")
|
||||
|
||||
|
||||
def analyze_database_stats() -> None:
|
||||
"""执行 ANALYZE,刷新统计信息,提升复杂查询稳定性。"""
|
||||
_execute_db_statement("ANALYZE", commit=True)
|
||||
logger.info("[DB维护] ANALYZE 已完成")
|
||||
|
||||
|
||||
def checkpoint_database_wal() -> None:
|
||||
"""定期执行 WAL checkpoint,控制 WAL 文件体积。"""
|
||||
row = _execute_db_statement(
|
||||
f"PRAGMA wal_checkpoint({DB_WAL_CHECKPOINT_MODE})",
|
||||
fetchone=True,
|
||||
)
|
||||
if row:
|
||||
logger.debug(f"[DB维护] WAL checkpoint({DB_WAL_CHECKPOINT_MODE}) 结果: {tuple(row)}")
|
||||
else:
|
||||
logger.debug(f"[DB维护] WAL checkpoint({DB_WAL_CHECKPOINT_MODE}) 已执行")
|
||||
|
||||
|
||||
def start_database_maintenance_scheduler() -> None:
|
||||
"""启动数据库维护调度器。"""
|
||||
_start_daemon_loop(
|
||||
"db-optimize",
|
||||
startup_delay=180,
|
||||
interval_seconds=DB_PRAGMA_OPTIMIZE_INTERVAL_SECONDS,
|
||||
job=optimize_database_runtime,
|
||||
error_tag="[DB维护] PRAGMA optimize 执行失败",
|
||||
)
|
||||
|
||||
if DB_ANALYZE_INTERVAL_SECONDS > 0:
|
||||
_start_daemon_loop(
|
||||
"db-analyze",
|
||||
startup_delay=300,
|
||||
interval_seconds=DB_ANALYZE_INTERVAL_SECONDS,
|
||||
job=analyze_database_stats,
|
||||
error_tag="[DB维护] ANALYZE 执行失败",
|
||||
)
|
||||
|
||||
if DB_WAL_CHECKPOINT_INTERVAL_SECONDS > 0:
|
||||
_start_daemon_loop(
|
||||
"db-wal-checkpoint",
|
||||
startup_delay=420,
|
||||
interval_seconds=DB_WAL_CHECKPOINT_INTERVAL_SECONDS,
|
||||
job=checkpoint_database_wal,
|
||||
error_tag="[DB维护] WAL checkpoint 执行失败",
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"[DB维护] 调度器已启动: "
|
||||
f"optimize={DB_PRAGMA_OPTIMIZE_INTERVAL_SECONDS}s, "
|
||||
f"analyze={DB_ANALYZE_INTERVAL_SECONDS}s, "
|
||||
f"checkpoint={DB_WAL_CHECKPOINT_INTERVAL_SECONDS}s({DB_WAL_CHECKPOINT_MODE})"
|
||||
)
|
||||
|
||||
|
||||
def start_kdocs_monitor() -> None:
|
||||
"""启动金山文档状态监控"""
|
||||
_start_daemon_loop(
|
||||
|
||||
Reference in New Issue
Block a user