Files
hfb_sys/docs/数据库SQL约束与运维.md
T

4.2 KiB
Raw Blame History

数据库 SQL 约束与运维

本项目使用 MySQL 8.4、GORM 和 Goose。本文是提交、上线和故障排查的数据库基线;SQL 静态检查不能替代真实数据量下的执行计划。

提交前约束

新增或修改 SQL、GORM 查询或迁移必须满足:

  1. 列表查询必须有分页、最大数量或明确日期范围,禁止无界读取订单、流水、消息和日志历史。
  2. GROUP BYCOUNT(DISTINCT)、窗口函数、跨表聚合、UNION 和相关子查询必须在接近生产数据量的 MySQL 上保存 EXPLAIN FORMAT=JSONEXPLAIN ANALYZE 结果。
  3. 高频查询先限定当前时间范围或当前页 ID,再做关联和聚合;禁止读取用户全部历史记录后在应用层过滤。
  4. 新增索引必须通过新的 Goose migration 提交,并在迁移注释中说明覆盖的查询条件、排序和基数;大表索引要评估锁影响和上线窗口。
  5. SQL 值必须使用 GORM 参数绑定或 ? 占位符,禁止拼接请求参数。动态排序字段只能来自白名单。
  6. 已应用的迁移文件禁止修改或删除,只能新增迁移完成结构修复;除 000001_init.sql 外的新迁移必须包含 -- +goose Up-- +goose Down
  7. 角色、权限、推送渠道、客服组等小型配置表允许全量读取,但必须保持数量边界或在本文件的白名单中登记;业务数据不得套用该例外。

本地 scripts/check.sh 会执行 scripts/check-sql-guard.sh,保护关键索引、时间范围和迁移完整性。它只防止关键代码被重构移除,不判断执行计划是否优秀。

执行计划

在维护库或只读副本上替换真实参数后执行:

EXPLAIN FORMAT=JSON
SELECT ...;

EXPLAIN ANALYZE
SELECT ...;

重点检查扫描行数、实际返回行数、索引使用、临时表、文件排序和 join 顺序。财务首页的仪表盘、结算明细和提现合并列表属于必须定期复核的查询。

生产观测

生产 MySQL 应保持 performance_schema 开启,并启用慢查询日志。项目的 deploy/mysql/my.cnf 默认记录超过 500ms 的语句;应用日志只记录 SQL 形状、耗时和返回行数,不记录绑定参数值。

常用排查 SQL

SELECT
  DIGEST_TEXT,
  COUNT_STAR,
  ROUND(SUM_TIMER_WAIT / 1000000000000, 2) AS total_seconds,
  ROUND(AVG_TIMER_WAIT / 1000000000, 2) AS avg_ms,
  SUM_ROWS_SENT,
  SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 30;

SELECT THREAD_ID, EVENT_NAME, TIMER_WAIT, SQL_TEXT, ROWS_EXAMINED
FROM performance_schema.events_statements_current
WHERE SQL_TEXT IS NOT NULL
ORDER BY TIMER_WAIT DESC;

应用慢查询阈值由 DATABASE_SLOW_QUERY_THRESHOLD_MS 配置。阈值调整后要同步检查 MySQL long_query_time,避免应用和数据库观测口径长期不一致。

连接、超时与容量

  • DATABASE_MAX_OPEN_CONNS 是单个 backend 实例的连接上限,总量必须按实例数核算,不能简单随实例扩容同比增加。
  • DATABASE_MAX_IDLE_CONNSDATABASE_CONN_MAX_LIFETIME_MINUTESDATABASE_CONN_MAX_IDLE_TIME_MINUTES 控制空闲连接和连接轮换。
  • 请求必须设置 Go context 截止时间;锁等待由 MySQL innodb_lock_wait_timeout 控制。长报表查询应进入异步任务或汇总表。
  • 数据量增长后,排行榜、财务历史统计和审计报表应迁移到日汇总表、缓存或只读副本,不能持续依赖在线全表聚合。
  • 修改连接池或容器资源后,用 docker compose config 核对最终插值;资源限额应高于稳定 RSS 峰值并留出数据库连接和备份余量。

备份与恢复

生产使用 XtraBackup 全量备份加 MySQL ROW binlog 归档实现时间点恢复。备份对象先客户端加密,再使用独立 OSS bucket 的服务端加密;恢复必须在隔离目录和隔离 MySQL 容器演练,禁止直接向生产实例回放。

./scripts/backup-online.sh status
./scripts/archive-binlog.sh verify
./scripts/restore-online.sh prepare <complete.env-OSS-URI>

备份完成标识、SHA-256、manifest、server UUID 和 Goose 版本必须一致;恢复演练至少按月验证一次,并记录恢复时间点和结果。