# 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 直接执行: ```bash 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 环境导出业务数据: ```bash 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 数据库: ```bash 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 ``` 导入后检查: ```bash .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,因为其中包含用户资料和密码哈希: ```bash shred -u /tmp/hulumath-django-data.json ``` ## 旧 Flask SQLite 旧 Flask `miniapp_v3.db` 的表结构与新 Django 模型不同,不能用 `loaddata`。 迁移前必须先确认需要保留的表和字段,再编写一次性 ETL: ```text 读取旧 SQLite → 字段清洗与用户映射 → 写入 MySQL Staging → 核对数量和抽样内容 → 生产停写窗口 → 最终增量迁移 → 切换域名 ``` 如果旧站没有真实用户数据,建议不迁移旧运行数据,直接使用新 MySQL 空库和官方种子。 ## 不允许的迁移方式 - 不复制 MySQL 5.7 数据目录给 MySQL 8。 - 不把 SQLite 文件放进 MySQL 数据目录。 - 不直接修改 Django migration 历史记录。 - 不在没有 `mysqldump` 备份时执行生产迁移。 - 不让 MySQL 5.7 与 8.0 共用同一数据目录。