数据迁移计划:lingniu_prod → 新系统
Context
老系统 lingniu_prod(单库 255 张表)需要全量迁移到新系统的 3 个库。新系统已做架构重构:拆分为 ln_asset_management(资产管理)、ln_energy(能源计费)、ry-cloud(系统核心/RuoYi 框架)。新库中现有数据为测试数据,迁移前清空。
源与目标
|
源 |
目标 |
| Host |
rm-uf65w5v2r77n674x2ko.mysql.rds.aliyuncs.com |
47.100.22.206:3306 |
| 用户 |
oneos_read (只读) |
root |
| 数据库 |
lingniu_prod (255 表) |
ln_asset_management (114), ln_energy (19), ry-cloud (29) |
ID 策略
ln_asset_management / ln_energy:IdType.AUTO(MySQL 自增),插入时不指定 ID,获取 LAST_INSERT_ID
ry-cloud:雪花算法 ID(已有数据如 sys_user ID = 2038797628680523778)
所有迁移记录保存到 ln_migration.id_mapping 表,维护 (old_table, old_id) → (new_table, new_id) 映射。
通用字段转换规则
| 老字段 |
新字段 |
转换 |
is_deleted (tinyint 0/1) |
del_flag (char '0'/'1') |
str(val) |
creater_id (bigint) |
create_by (bigint) |
查 user id_mapping |
updater_id (bigint) |
update_by (bigint) |
查 user id_mapping |
int 枚举 (如 truck_type) |
varchar 字典码 |
查 dict_mapping |
datetime |
date |
取日期部分 |
double |
decimal |
Decimal(str(val)) |
迁移分阶段执行
Phase 0: 准备
- 在目标库创建
ln_migration 数据库和 id_mapping 表
- 清空目标库 3 个库中所有业务表数据(保留 ry-cloud 框架种子数据如 sys_config, sys_oss_config, sys_tenant)
- 读取老库
tab_dic 构建枚举映射字典 → dict_mapping.py
Phase 1: 基础数据(无 FK 依赖)
| 老表 |
新表 (库) |
行数 |
说明 |
tab_dic |
sys_dict_type + sys_dict_data (ry-cloud) |
681 |
按 dic_type 分组为 type+data |
tab_region |
common_district (asset) |
3,359 |
直接映射 |
tab_vehicle_model |
vehicle_model (asset) |
39 |
字段对齐 |
tab_insurance_company |
insurance_company (asset) |
20 |
直接映射 |
tab_hydrogen_site |
hydrogen_station (asset) |
101 |
int→varchar 枚举 |
tab_parking |
parking_lot_info (asset) |
65 |
直接映射 |
tab_maintain_site |
repair_station (asset) |
64 |
直接映射 |
tab_rescue_site |
rescue_team (asset) |
~14 |
直接映射 |
tab_annual_review_service_station |
inspection_station (asset) |
14 |
直接映射 |
tab_truck_check_item |
vehicle_check_item (asset) |
294 |
直接映射 |
tab_contract_templates |
contract_template (asset) |
13 |
直接映射 |
tab_charge_station |
charging_station (asset) |
~数条 |
直接映射 |
Phase 2: 系统数据(用户/组织/角色)
| 老表 |
新表 (ry-cloud) |
行数 |
说明 |
tab_org |
sys_dept + sys_organization |
19 |
重建 ancestors 字段 |
tab_user |
sys_user |
405 |
密码需重置为 BCrypt 临时密码 |
tab_role |
sys_role |
69 |
雪花 ID |
tab_user_role |
sys_user_role |
201 |
查 user+role id_mapping |
tab_menu |
sys_menu |
464 |
评估:新系统菜单已重新定义,可能跳过 |
tab_role_menu |
sys_role_menu |
6,236 |
依赖菜单决策 |
密码处理:老系统使用自定义 salt+hash,新系统使用 BCrypt。迁移时统一设置临时密码(如 Abc@123456 的 BCrypt 值),首次登录强制修改。
Phase 3: 核心业务实体
| 老表 |
新表 (asset) |
行数 |
复杂度 |
tab_truck |
vehicle_info |
1,203 |
高:47→29 列,大量字段重组 |
tab_truck_status_info |
vehicle_status |
1,385 |
中:int→varchar 枚举 |
tab_driver |
driver_info |
212 |
低 |
tab_customer |
customer_info |
310 |
中 |
tab_truck_licence |
vehicle_license |
1,712 |
中:truck_id→vehicle_id FK |
tab_truck_insure |
insurance_procurement |
740 |
中:15→32 列扩展 |
tab_equipment_info |
aftermarket_device |
1,562 |
中 |
tab_violation_management |
traffic_violation |
1,285 |
低 |
tab_accident + tab_accident_cost_bearing |
accident_info + accident_expense |
293+823 |
中 |
tab_failure |
vehicle_fault_manage |
5,140 |
低 |
tab_vehicle_annual_inspection |
vehicle_annual_inspection |
353 |
低 |
tab_vehicle_preparation |
prepare_car |
1,736 |
低 |
tab_customer_invoice |
invoice_info |
219 |
低 |
tab_truck_device_info |
aftermarket_device 或 vehicle_realtime_location |
1,227 |
评估 |
tab_training_materials |
training_material (asset) |
3 |
低 |
vehicle_info 字段映射(核心):
Phase 4: 合同域
| 老表 |
新表 (asset) |
行数 |
说明 |
tab_contract |
vehicle_lease_contract_info |
681 |
38→67 列,大量新字段 NULL |
tab_contract_rent_order |
vehicle_lease_order |
679 |
关联合同 |
tab_contract_rent_truck |
vehicle_lease_order_detail |
3,865 |
关联 order + vehicle |
tab_contract_rent_truck_service_cost |
vehicle_lease_order_service_item |
1,645 |
关联 detail |
tab_contract_thirty_party |
contract_authorized_person |
682 |
直接映射 |
tab_contract_authorizer_information |
contract_authorized_person |
666 |
合并 |
tab_contract_costs |
template_* 系列表 |
15,059 |
按费用类型拆分 |
tab_contract_hydrogen_fees |
template_hydrogen_fee |
13 |
直接映射 |
Phase 5: 交付/退车/换车
| 老表 |
新表 (asset) |
行数 |
说明 |
tab_truck_rent_task |
delivery_task_subject |
3,104 |
任务容器 |
tab_truck_rent_take |
delivery_order + delivery_vehicle |
1,956 |
一拆多 |
tab_truck_rent_return |
return_vehicle_task |
1,079 |
重构 |
tab_truck_rent_return_cost |
return_fees |
73 |
直接映射 |
tab_truck_rent_return_dep_cost |
return_settlement_* 子表 |
4,634 |
按类型拆分 |
tab_truck_rent_replace |
vehicle_replacement |
247 |
直接映射 |
tab_standby_vehicle_main/detail |
vehicle_abnormal_move |
377+2,171 |
评估映射 |
Phase 6: 账单/财务
| 老表 |
新表 (asset) |
行数 |
说明 |
tab_rent_contract_bill |
bills |
25,625 |
合同账单 |
tab_rent_contract_bill_truck |
vehicle_bills + vehicle_bill_service_items |
270,283 |
大表,批量处理 |
tab_rent_contract_bill_other_cost |
合并到 vehicle_bills |
~少量 |
|
tab_finance_receivable |
receivable_subject + receivable_vehicle |
10,308 |
拆分 |
tab_finance_deposit_receive |
customer_payment_receipt |
2,078 |
映射 |
tab_finance_deposit_deduction |
customer_payment_item |
52 |
映射 |
Phase 7: 能源域 → ln_energy
| 老表 |
新表 (ln_energy) |
行数 |
说明 |
tab_energy_account |
energy_account |
201 |
结构重组 |
tab_energy_project_account |
energy_account_project |
307 |
直接映射 |
tab_energy_account_recharge |
energy_recharge_order |
942 |
字段扩展 |
tab_import_hydrogen_order |
hydrogen_station_order |
58,642 |
加氢原始订单 |
tab_energy_hydrogen_bill |
energy_hydrogen_detail |
58,554 |
大表 |
tab_import_ele_charge_order |
electricity_charge_record |
4,405 |
充电原始订单 |
tab_energy_electricity_bill |
energy_bill_detail |
4,355 |
fee_type=electricity |
Phase 8: 附件
| 老表 |
新表 (asset) |
行数 |
说明 |
tab_data_attachment |
tab_data_attachment |
247,447 |
最大表之一,data_id 需 FK 重映射 |
tab_image_attachment |
合并到 tab_data_attachment 或保留 |
51,516 |
评估 |
Phase 9: 其他
| 老表 |
新表 |
行数 |
处理 |
tab_maintain_maintenance_project |
评估 |
243,474 |
新系统无直接对应,可能跳过 |
tab_truck_rent_form_data |
评估 |
456,061 |
表单数据,新系统结构不同 |
tab_preparation_form_data |
评估 |
171,497 |
同上 |
tab_standby_vehicle_form_data |
评估 |
143,034 |
同上 |
暂不迁移的表(无新系统对应)
- 审批流:
tab_approve_instance*, tab_approve_template_node
- 工作流:
tab_flow_task*, tab_flow_template*
- G7 车联网:
tab_g7s_org, tab_g7s_truck_mileage (289K), tab_g7s_in_out_event (159K)
- 培训考试:
tab_train_*, tab_safety_training
- 系统日志:
tab_api_access_log (4.6M), tab_user_log, tab_user_message, tab_short_message
- 调度记录:
tab_schedule_execute_result (347K), tab_data_sync_task_record
- 应用版本:
tab_app_version, tab_version_user_check, tab_release_version_log
- 临时表:所有
tab_aa_temp_*, *_copy*, temp_*
- 视图:所有
view_*, v_*
- 汇总表:
truck_info, truck_equipment_info, truck_hydrogen_info, truck_mileage, truck_parking
实现方案:Python 脚本
目录结构
关键技术点
- 批量处理:大表(27 万+ 行)使用
SSCursor 服务端游标 + executemany 批量写入(每批 1000 行)
- ID 映射:
ln_migration.id_mapping(source_table, source_id, target_db, target_table, target_id),FK 字段通过查映射表解析
- 枚举映射:从
tab_dic 读取所有字典项,预构建 {(dic_type, int_value): new_dict_code} 映射
- 密码处理:所有用户密码统一设为 BCrypt(
Abc@123456),首次登录强制修改
- 事务:每个 Phase 按表粒度 commit,失败可单表重试
验证策略
- 行数校验:每张表迁移后对比源/目标行数
- 抽样比对:每张核心表随机取 10 条,比对关键业务字段
- FK 完整性:检查所有外键列无孤儿记录
- 业务逻辑:能源账户余额一致、合同-车辆关联完整
- 登录测试:使用临时密码验证 sys_user 登录
回滚方案
- 迁移前对目标 3 库做
mysqldump 备份
- 回滚 = truncate 所有目标表 + 从备份恢复 + drop
ln_migration
- 单 Phase 回滚 = 根据
id_mapping 删除该 Phase 写入的记录
关键文件
ln-asset-management/.../BaseEntity.java — IdType.AUTO, del_flag char(1)
ln-asset-management/.../VehicleInfo.java — 新车辆实体 29 字段
ln-cloud/ruoyi-common/.../BaseEntity.java — RuoYi 基础实体
- 老后端代码
/Users/kkfluous/Projects/lingniu/ln_asset/lingniu_asset_server/lingniu-manager/src/main/java/org/lingniu/manager/model/ — 所有老实体类