feat: 数据库连接层改造——库目标由 .env 装配 + 环境防呆(迁 MySQL 第一步)

为把数据库从单文件 SQLite 迁到 MySQL 5.7 铺路。本期不改后端:
DB_HOST 为空时仍走 SQLite,本地开发无感。

- config.py: 新增 DEPLOY_ENV(默认 dev)与 DB_HOST/PORT/USER/PASSWORD/NAME/
  CHARSET/COLLATION、DATABASE_URL、两个逃生阀(DB_ALLOW_ENV_MISMATCH /
  DB_ALLOW_SQLITE_FALLBACK)
- core/db_config.py(新增): URI 组装;按方言分叉的引擎参数(utf8mb4、
  pool_pre_ping、pool_recycle=1800、READ COMMITTED、STRICT_TRANS_TABLES);
  连接探活;app_meta 方言中立读写(MySQL 里 key 是保留字,需反引号)
- 防混库三层: ①库名与环境绑定(dev→auto_control_dev / prod→auto_control)
  ②库标签 app_meta.deployment_env 与 .env 声明比对 ③启动横幅打印当前库
  (生产用 WARNING 级)。不符直接拒绝启动并说明两边分别是什么
- web_server.py: 硬编码 sqlite URI → db_config;配置错在装配期就 exit 2;
  init_db 之后跑库标签校验 + 横幅
- core/models.py: PRAGMA 监听器加 sqlite 类型守卫——它挂在 Engine 基类上,
  MySQL 连接执行 PRAGMA 会直接导致建连失败
- requirements.txt 加 PyMySQL;scripts/start.sh 依赖守卫加 pymysql,
  并在 exec 前打印 DEPLOY_ENV/DB_NAME/DB_HOST
- .env.example 新增「数据库」段;DEVELOPMENT.md §4.1/4.2、DEPLOY.md §2.2 同步

验证: 用 DATABASE_URL 指向 users.db 的一致快照副本跑通主要只读接口
(health/devices/jobs/pool/groups/discovery/summary 全 200,app_meta 读写正常);
DEPLOY_ENV=prod 且无 DB_HOST 时退出码 2;开 DB_ALLOW_SQLITE_FALLBACK 后可回退。
This commit is contained in:
2026-09-13 10:27:14 +08:00
parent 933225784b
commit f22263ab45
9 changed files with 374 additions and 4 deletions
+27
View File
@@ -47,6 +47,33 @@ else:
# 部署后需执行 chmod +x bin/adb/adb
ADB_PATH = os.path.join(_ADB_DIR, "adb")
# ================== 数据库 ==================
# 平台支持 MySQL(正式用法)与 SQLite(仅作回退,见 core/db_config.py)。
#
# DEPLOY_ENV 声明"这套配置连的是哪个环境的库",与库名一一绑定:
# dev → auto_control_dev(本地开发,可随意折腾)
# prod → auto_control (正式数据)
# 启动时会校验「.env 声明的环境」与「目标库登记的环境」是否一致,
# 不一致直接拒绝启动——防止把开发配置连到生产库上。
DEPLOY_ENV = _env("DEPLOY_ENV", "dev").strip().lower()
DB_HOST = _env("DB_HOST", "") # 为空则回退 SQLite(生产禁止静默回退)
DB_PORT = int(_env("DB_PORT", "3306"))
DB_USER = _env("DB_USER", "")
DB_PASSWORD = _env("DB_PASSWORD", "") # 写入 .env,不要提交到 git
DB_NAME = _env("DB_NAME", "")
DB_CHARSET = _env("DB_CHARSET", "utf8mb4")
# 排序规则用 _bin(逐码点比较,等价 SQLite 的大小写敏感语义)。
# 用默认的 utf8mb4_general_ci 会让 Admin/admin、Phone1/phone1 被判重复。
DB_COLLATION = _env("DB_COLLATION", "utf8mb4_bin")
# 完整连接串(优先级最高,迁移/回归脚本用它临时指向别的库)
DATABASE_URL = _env("DATABASE_URL", "")
# 逃生阀(默认关;仅在你明确知道自己在干什么时打开)
DB_ALLOW_ENV_MISMATCH = _env("DB_ALLOW_ENV_MISMATCH", "0") == "1"
DB_ALLOW_SQLITE_FALLBACK = _env("DB_ALLOW_SQLITE_FALLBACK", "0") == "1"
# ================== Web 后台 ==================
WEB_HOST = "0.0.0.0"
# 端口必须避开 Windows 动态端口范围(本机被改成 1024-15000,默认 49152-65535)