后端-数据库-跨版本表结构不一致导致数据导入失败
问题现象
- 从服务器导出
recommendation_scores表后,用mysql < dump.sql导入本地时报错 - 错误信息:
ERROR 1054 (42S22): Unknown column 'llm_score' in 'field list' - 服务器和本地虽然都用 MySQL,但表结构版本不同
核心问题
- 服务器运行 AI 推荐 v2 版本,
recommendation_scores表有 12 列(含 llm_score、 negative_penalty、topic_score、depth_score、utility_score、source_score、topic_label) - 本地已升级为 AI 推荐 v4 版本,同表只有 6 列(id、news_type、news_id、 final_score、score_reason、scored_at)
mysqldump --complete-insert生成的 INSERT 语句包含服务器所有列名,导入时因缺列失败
关键差异列对比: | 服务器 (v2) | 本地 (v4) | |------------|----------| | llm_score | (删除) | | negative_penalty | (删除) | | topic_score | (删除) | | depth_score | (删除) | | utility_score | (删除) | | source_score | (删除) | | topic_label | (删除) | | (无) | score_reason |
解决方法
方案:仅导出公共列,生成自定义 INSERT 语句
- 用 SQL
CONCAT在服务器端直接生成只包含公共列的 INSERT:
ssh news "mysql -u root -p'xxx' news -e \
\"SELECT CONCAT(
'INSERT INTO recommendation_scores (news_type, news_id, final_score, scored_at) VALUES (',
QUOTE(news_type), ', ',
news_id, ', ',
IFNULL(final_score, 'NULL'), ', ',
QUOTE(scored_at), ');'
) FROM recommendation_scores WHERE final_score IS NOT NULL;\"" \
2>/dev/null > insert.sql
- 去掉 mysql 输出的表头行(第 1 行是列名 CONCAT(...)):
tail -n +2 insert.sql > insert_clean.sql
- 导入本地:
# 导入前禁用外键检查以确保 TRUNCATE 能执行
mysql -u root -p'xxx' news -e "SET FOREIGN_KEY_CHECKS=0; TRUNCATE TABLE recommendation_scores; SET FOREIGN_KEY_CHECKS=1;"
mysql -u root -p'xxx' news < insert_clean.sql
下次防错措施
-
导入前先对比表结构:
# 服务器 ssh news "mysql -u root -p'xxx' news -e 'DESCRIBE recommendation_scores;'" 2>/dev/null # 本地 mysql -u root -p'xxx' news -e "DESCRIBE recommendation_scores;" -
跨版本迁移时优先考虑脚本:不用 mysqldump 直接用,而是编写 Python 脚本做字段映射和转换
# 示例:用 SQLAlchemy 做字段级映射导入 from src.core.database import async_session_factory # 逐行读取源数据,按目标表结构映射后插入 -
模块版本变更时记录 Schema 差异:在模块升级文档中列出新增/删除/变更的列