# 7.6 数据库迁移工具 :::tip 概述 整库迁移器(internal/migrate + cmd/migrator)实现五方言互迁:源库内省 → 中间表示 → 目标方言 DDL → 分批搬运 → 序列修复 → 行数校验。纯 CLI、gdb 动态建连裸读裸写(不走 dao,不触发全局钩子)。 ::: ## 五阶段流程 ```text ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ 1/5 建目标库│──▶│ 2/5 建表结构│──▶│ 3/5 搬运数据│──▶│ 4/5 序列修复│──▶│ 5/5 行数校验│ │ ensureDB │ │ 内省→建表 │ │ 分批 INSERT│ │ setval等 │ │ COUNT 对比 │ │ (不存在才建)│ │ →建索引 │ │ 进度回调 │ │ │ │ PASS/FAIL │ └────────────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ drop-first: 无主键表报错跳过 pgsql/mssql 专项 不一致→ 先 DropAllTables 其余方言免修 整体失败 非清空: 同名表拦截跳过 ``` ## CLI 参数 ```sh go run ./cmd/migrator \ -src-type=mysql -src-host=127.0.0.1 -src-hostport=3306 \ -src-database=easygoadmin.goframe.elevue -src-username=root -src-password=root \ -dst-type=pgsql -dst-host=127.0.0.1 -dst-hostport=5432 \ -dst-database=easygoadmin.goframe.elevue -dst-username=postgres -dst-password=123456 \ -drop-target-first ``` | 参数组 | 键 | 默认 | |--------|-----|------| | 源库 | -src-type / host / hostport / database / username / password | mysql / 127.0.0.1 / 3306 / — / root / — | | 目标库 | -dst-type / host / hostport / database / username / password | pgsql / 127.0.0.1 / 5432 / — / postgres / — | | 行为 | -drop-target-first | 迁移前清空目标库**全部表**(慎用) | | | -tables | 只迁指定表(逗号分隔白名单,留空迁全部) | | | -batch-size | 数据搬运批大小(默认 1000) | ## 核心设计 ```text 独立于业务基座: gdb.New 动态连接源库与目标库(独立命名节点 migrate_src/migrate_dst, 不触碰 config.yaml 默认连接),裸读裸写—— 全程不触发全局钩子(租户隔离/软删/审计盖章),数据原样落库 五方言目标渲染器(Renderer 接口:Quote/Column/CreateTable/CreateIndex/ DropAllTables/FixSequence): mysql AUTO_INCREMENT + COMMENT 内联 pgsql IDENTITY + COMMENT ON 独立语句 + setval 序列修复 + CASCADE sqlite 极简类型 + AUTOINCREMENT + 免修序 mssql IDENTITY + NVARCHAR + 扩展属性注释 + 内联 INSERT(绕 2100 参数上限) + DBCC CHECKIDENT 修序 oracle IDENTITY + NUMBER/NVARCHAR2 + COMMENT ON + 免修序 中间表示(IR):20 种归一类型;剥离 unsigned/pgsql 时区修饰; tinyint(1)→bool;索引命名统一 uk_/idx_ 规范(迁移后全库一种命名) 数据搬运 doCopy:主键游标分页;无主键表直接报错("请先补主键") ``` ## 数据搬运循环图(doCopy,主键游标分页) ```text lastPK=nil │ ▼ ┌──────────────────────────────────────────┐ │ SELECT 列集 FROM src.table │ │ WHERE pk > lastPK ORDER BY pk LIMIT N │◀──────┐ └──────────────┬───────────────────────────┘ │ 行数=0?─ 是 ─▶ 返回 total │ 否 │ ▼ │ batch=[{列:值(字节转字符串)}…],lastPK=末行 pk ────┘ │ ▼ 目标写入:通用方言 → 参数化多行 INSERT mssql → 内联字面量 INSERT(自增列:事务内 IDENTITY_INSERT ON/OFF) │ ▼ total += len(batch);onBatch 进度回调;len(batch)