Files
Hulumath-Web/docs/MYSQL8_MIGRATION.md
T
Jacky 1f98f7152d
CI / test (push) Failing after 1m31s
v0.2 Preview: Construction Plan.
2026-08-08 21:25:27 +08:00

2.8 KiB
Raw Blame History

MySQL 8.0.35 迁移说明

当前状态

生产数据库目标为 MySQL 8.0.35

  • Django 驱动:mysqlclient
  • 字符集:utf8mb4
  • 排序规则:utf8mb4_0900_ai_ci
  • 存储引擎:InnoDB
  • 事务隔离:READ COMMITTED
  • SQL 模式:STRICT_TRANS_TABLES
  • 实时匹配:MySQL 8 SELECT ... FOR UPDATE SKIP LOCKED

MySQL 5.7 不受支持。生产检查会拒绝版本低于 8.0.35 的数据库。

新空库

新安装的 MySQL 8 直接执行:

set -a
source .env.production
set +a

.venv-production/bin/python backend/manage.py check_mysql
.venv-production/bin/python backend/manage.py migrate --noinput
.venv-production/bin/python backend/manage.py seed_initial_content
.venv-production/bin/python backend/manage.py seed_contests

从当前 Django SQLite 搬数据

仅适用于本仓库 Django 创建的 backend/db.sqlite3,不适用于旧 Flask 的 miniapp_v3.db

先在旧 SQLite 环境导出业务数据:

unset DATABASE_URL

.venv/bin/python backend/manage.py dumpdata \
  --natural-foreign \
  --natural-primary \
  --exclude contenttypes \
  --exclude auth.permission \
  --exclude admin.logentry \
  --exclude sessions.session \
  --indent 2 \
  --output /tmp/hulumath-django-data.json

切换到空 MySQL 8 数据库:

set -a
source .env.production
set +a

.venv-production/bin/python backend/manage.py check_mysql
.venv-production/bin/python backend/manage.py migrate --noinput
.venv-production/bin/python backend/manage.py loaddata /tmp/hulumath-django-data.json

导入后检查:

.venv-production/bin/python backend/manage.py shell -c "
from accounts.models import User
from math_life.models import StoryRun
from contest.models import ContestAttempt
print({
    'users': User.objects.count(),
    'story_runs': StoryRun.objects.count(),
    'contest_attempts': ContestAttempt.objects.count(),
})
"

确认无误后安全删除中间 JSON,因为其中包含用户资料和密码哈希:

shred -u /tmp/hulumath-django-data.json

旧 Flask SQLite

旧 Flask miniapp_v3.db 的表结构与新 Django 模型不同,不能用 loaddata

迁移前必须先确认需要保留的表和字段,再编写一次性 ETL:

读取旧 SQLite
→ 字段清洗与用户映射
→ 写入 MySQL Staging
→ 核对数量和抽样内容
→ 生产停写窗口
→ 最终增量迁移
→ 切换域名

如果旧站没有真实用户数据,建议不迁移旧运行数据,直接使用新 MySQL 空库和官方种子。

不允许的迁移方式

  • 不复制 MySQL 5.7 数据目录给 MySQL 8。
  • 不把 SQLite 文件放进 MySQL 数据目录。
  • 不直接修改 Django migration 历史记录。
  • 不在没有 mysqldump 备份时执行生产迁移。
  • 不让 MySQL 5.7 与 8.0 共用同一数据目录。