2.8 KiB
2.8 KiB
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 共用同一数据目录。