Files
dekun 52aca456e9 Add PostgreSQL production backend to eliminate SQLite lock contention.
Support DATABASE_URL with connection pooling, pg_dump backups, SQLite migration script, and deploy_postgres.sh with docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 08:11:42 +08:00

7.3 KiB
Raw Permalink Blame History

PostgreSQL 生产数据库

qihuo 支持两种存储后端:

模式 配置 适用场景
SQLite(默认) 不设置 DATABASE_URL 本地开发、单机轻量试用
PostgreSQL(推荐生产) .envDATABASE_URL=postgresql://... 7×24 运行、多线程并发、消除 database is locked

配置 DATABASE_URL 后,应用自动使用 连接池(默认 2–20 连接),无需改业务代码。


为什么用 PostgreSQL

SQLite 在同一文件上同一时刻只允许一个写者。qihuo 单进程内有多路后台线程(持仓刷新、止盈守护、挂单同步、统计缓存等)和 HTTP 请求同时写库,容易出现:

position worker failed: database is locked
bootstrap position snapshot: database is locked

PostgreSQL 面向并发读写设计,多连接、行级锁、连接池,与专业交易软件「服务端数据库 + 内存快照」的思路一致。


一键部署(新服务器 / 已有 qihuo)

在已执行过 deploy.sh 的服务器上,以 root 运行:

cd /opt/qihuo
git pull   # 获取最新代码
sudo bash scripts/deploy_postgres.sh

脚本会自动:

  1. 安装 postgresql / postgresql-contrib
  2. 创建数据库 qihuo、用户 qihuo(随机密码,终端会打印)
  3. 写入 /opt/qihuo/.envDATABASE_URLPG_POOL_MINPG_POOL_MAX
  4. pip install psycopg psycopg-pool
  5. 执行 init_db() 建表
  6. pm2 restart qihuo --update-env

从现有 SQLite 迁移

/opt/qihuo/futures.db 已有数据:

cd /opt/qihuo
MIGRATE_SQLITE=1 sudo bash scripts/deploy_postgres.sh

会:

  • 初始化 PostgreSQL 表结构
  • 运行 scripts/migrate_sqlite_to_postgres.py 导入全部表
  • 将旧库备份为 futures.db.pre_pg.YYYYMMDD_HHMMSS(可用 BACKUP_SQLITE=0 跳过)

迁移前建议先做一次 Web 设置页 立即备份 或:

cp /opt/qihuo/futures.db /root/futures.db.bak.$(date +%Y%m%d)
pm2 stop qihuo
MIGRATE_SQLITE=1 sudo bash scripts/deploy_postgres.sh

环境变量(可选)

变量 默认 说明
APP_DIR /opt/qihuo 应用目录
PG_DB qihuo 数据库名
PG_USER qihuo 数据库用户
PG_PASSWORD 随机 不设则脚本生成
PG_HOST 127.0.0.1 主机
PG_PORT 5432 端口
MIGRATE_SQLITE 0 1 时从 futures.db 迁移
BACKUP_SQLITE 1 迁移后是否备份旧 SQLite 文件

手动部署

1. 安装 PostgreSQLUbuntu

apt update
apt install -y postgresql postgresql-contrib
systemctl enable postgresql
systemctl start postgresql

2. 创建库与用户

sudo -u postgres psql <<'SQL'
CREATE USER qihuo WITH PASSWORD '请改为强密码';
CREATE DATABASE qihuo OWNER qihuo;
GRANT ALL PRIVILEGES ON DATABASE qihuo TO qihuo;
SQL

3. 配置 .env

cd /opt/qihuo
cat >> .env <<'EOF'

DATABASE_URL=postgresql://qihuo:请改为强密码@127.0.0.1:5432/qihuo
PG_POOL_MIN=2
PG_POOL_MAX=20
EOF

4. 安装 Python 驱动并初始化

source venv/bin/activate
pip install -r requirements.txt
export $(grep -v '^#' .env | xargs)   # 或手动 export DATABASE_URL
python3 -c "from app import init_db; init_db()"

5. 迁移 SQLite(可选)

python3 scripts/migrate_sqlite_to_postgres.py --sqlite /opt/qihuo/futures.db
# 仅预览行数:
python3 scripts/migrate_sqlite_to_postgres.py --dry-run

6. 重启应用

pm2 restart qihuo --update-env
pm2 logs qihuo --lines 30

启动后日志中不应再频繁出现 database is lockedSQLite 特有)。


连接池

变量 默认 说明
PG_POOL_MIN 2 池内最少连接
PG_POOL_MAX 20 池内最多连接

每个 HTTP 请求 / 后台 worker 从池中借连接,用毕归还。PM2 请保持 instances: 1(见 ecosystem.config.cjs);若要多实例,共用同一 DATABASE_URL 即可,PostgreSQL 可承受。


备份

方式一:系统设置页(推荐)

系统设置 → 数据备份与恢复 → 立即备份

PostgreSQL 模式下包内为 postgres_dump.sqlpg_dump 逻辑备份),而非 futures.db

方式二:命令行

# 需与 .env 中 DATABASE_URL 一致
source /opt/qihuo/venv/bin/activate
set -a && source /opt/qihuo/.env && set +a
pg_dump --no-owner --no-acl -f /root/qihuo_backup/manual_$(date +%Y%m%d_%H%M%S).sql "$DATABASE_URL"

方式三:每日自动备份

设置页开启 每日自动备份(默认 03:00),保留份数默认 30。备份目录默认 /root/qihuo_backup

详见 BACKUP.md


恢复

从 qihuo 备份包恢复(含 restore.sh

pm2 stop qihuo
cd /root
tar -xzf qihuo_backup_YYYYMMDD_HHMMSS.tar.gz
cd qihuo_backup_YYYYMMDD_HHMMSS
# 确保 /opt/qihuo/.env 已配置 DATABASE_URL
export RESTORE_DIR=/opt/qihuo
chmod +x restore.sh
./restore.sh
pm2 restart qihuo

manifest.json"backend": "postgres" 表示包内为 postgres_dump.sql

手工 psql 恢复

pm2 stop qihuo
export DATABASE_URL=postgresql://qihuo:密码@127.0.0.1:5432/qihuo
# 空库或需覆盖的库
psql "$DATABASE_URL" -f /path/to/postgres_dump.sql
cp -a uploads_backup/. /opt/qihuo/uploads/   # 若有附件
pm2 restart qihuo

恢复后检查

  1. Web 登录正常
  2. 交易记录统计 页数据完整
  3. 系统设置 中 CTP、资金等配置仍在
  4. 连接 CTP,持仓页刷新正常
  5. pm2 logs qihuo 无持续数据库报错

回退到 SQLite

  1. pm2 stop qihuo
  2. 注释或删除 .envDATABASE_URL
  3. 确保 /opt/qihuo/futures.db 存在(可用迁移前备份 futures.db.pre_pg.*
  4. pm2 restart qihuo

故障排查

现象 可能原因 处理
未安装 psycopg 未 pip install pip install -r requirements.txt
pg_dump 失败 未装客户端 / URL 错误 apt install postgresql-client;检查 DATABASE_URL
迁移后缺表 未 init_db python3 -c "from app import init_db; init_db()" 后重跑迁移
登录失败 只恢复了 SQL 未恢复 settings 检查 settings 表是否有 admin_password_hash
连接拒绝 PostgreSQL 未启动 systemctl status postgresql
仍见 locked 未切到 PG,仍用 SQLite grep DATABASE_URL /opt/qihuo/.envpm2 restart --update-env

验证当前后端

cd /opt/qihuo && source venv/bin/activate
set -a && source .env && set +a
python3 -c "from db_conn import database_label, db_backend; print(db_backend(), database_label())"

应输出 postgres PostgreSQL (...)

查看 PostgreSQL 连接

sudo -u postgres psql -d qihuo -c "SELECT count(*) FROM pg_stat_activity WHERE datname='qihuo';"

安全建议

  • DATABASE_URL 含密码,勿提交到 git.env 权限建议 chmod 600
  • 备份包、postgres_dump.sql 含交易与账号数据,勿上传公开网盘
  • 生产库仅监听 127.0.0.1,不暴露 5432 到公网
  • 定期测试 备份 → 解压 → restore.sh → 登录 全流程

相关文档