DataGrip数据库迁移实操:整库、多表、单表一步到位
如果你平时靠 Navicat 或者命令行做数据库迁移那我建议你花半小时把 DataGrip 摸熟。JetBrains 家的这个数据库客户端很多人只拿它写 SQL、看表结构其实它的数据迁移能力被严重低估了。整库搬、多表同步、单表导出导入它都能干而且跨数据库类型也能干——比如从 MySQL 整库搬到 GoldenDB或者从 SQL Server 抽几张表到 PostgreSQL这种活儿用 DataGrip 会比想象中顺手很多。这篇就用一个完整的实操视角讲清楚怎么用 DataGrip 做整库迁移、多表迁移和单表数据迁移包括环境准备、驱动配置、每一步怎么点、常见的坑怎么躲。适合正在做数据库搬迁、本地库和测试库之间同步数据、或者偶尔要从生产库捞几张表到本地分析的开发、运维和数据分析同学参考。1. 为什么我用 DataGrip 做迁移而不是继续用命令行先说个实在话mysqldump、pg_dump 这类原生工具在整库迁移场景下依然是最稳的方案这点我不否认。但 DataGrip 的价值不在“替代原生工具”而在“统一入口”和“可视化兜底”。我手上常年维护十来个环境MySQL、PostgreSQL、GoldenDB、SQL Server、Oracle 都混着用。以前做个数据同步得记一堆命令行参数mysqldump 要加什么参数才不乱码psql 的 COPY 语法和 mysql 的 LOAD DATA 语法又不一样Oracle 的 expdp/impdp 更是另一套逻辑。时间一长光查命令就花不少功夫。DataGrip 把这一层抽象掉了它把“导入”“导出”做成了统一的图形界面和右键菜单底层转换逻辑由 IDE 处理我只需要关注“从哪来、到哪去、要哪些数据”这三个问题。第二个用它的理由是跨库迁移太方便了。命令行工具通常只在同一种数据库之间迁移才省心跨库就得先导出成 SQL 脚本再改语法改到怀疑人生。DataGrip 的迁移是基于“数据读取 目标库写入”的它自己处理类型映射和方言差异。比如你从 SQL Server 导一张表到 GoldenDB它会把 nvarchar 映射成 varchar把 datetime 映射成 timestamp这些转换如果你手写 SQL得花不少时间。第三个理由是它对“部分迁移”特别友好。有时候你根本不需要整库搬你只需要把订单表最近三个月的几万行抽到本地或者把配置表的全部数据同步到测试环境。用命令行当然也能做但要写条件、写管道、处理编码而 DataGrip 里就是查出来、选中、右键导出或者直接跨库 Insert。对于“不想跟 shell 打交道”的场景它的效率是碾压级的。当然DataGrip 也不是万能的。它不适合超大表的物理级迁移比如一张表几个 TB那还是得用原生的物理备份或数据泵方案。但对于绝大多数开发、测试、分析场景它的迁移能力已经完全够用了。2. 环境准备安装、连接和驱动配置2.1 安装与首次启动配置用 DataGrip 的前提是先装好它。这里只提一句去 JetBrains 官网下载对应系统的安装包双击安装即可Windows、macOS、Linux 都有对应版本。装完之后首次启动会让你选主题、配快捷键方案这些按个人习惯来就行。真正需要注意的是许可证问题。DataGrip 是付费软件有 30 天试用期。试用到期后要么买正版授权要么用社区版替代工具。网上那些“破解版”“激活码”我劝你别碰一个是安全性没保障另一个是 JetBrains 对盗版打击越来越严公司电脑上装破解工具容易惹麻烦。如果只是临时用试用期足够你把迁移流程跑通了。如果你长期需要买个人授权其实是性价比很高的投资——对比你手写脚本花掉的时间这个钱早就赚回来了。语言方面DataGrip 默认是英文界面如果你看着不习惯可以在 Settings/Preferences 里装中文语言包插件装完重启就是中文。不过我的建议是开着英文界面因为大多数报错信息、官方文档都是英文界面用中文反而容易对不上号。2.2 数据库连接配置与常见驱动问题DataGrip 要操作数据库第一步是配连接。这里重点说说驱动Driver的问题因为踩坑的人太多了。DataGrip 内置了 MySQL、PostgreSQL、SQL Server、Oracle 等主流数据库的驱动新建连接时它会自动下载对应的 JDBC 驱动包。但国内网络环境下自动下载经常失败界面上会提示Download driver files卡住不动。解决办法有两个手动下载驱动包去对应数据库官网或者 Maven 中央仓库下载 JDBC 驱动 Jar 包然后在 DataGrip 的Database Explorer面板里找到对应数据源的Driver设置点号添加本地 Jar 包。添加完之后 DataGrip 会优先使用本地驱动。使用自定义驱动如果你连的是 GoldenDB、OceanBase、TiDB 这类国产或分布式数据库它们有些是基于 MySQL 协议兼容的有些需要专门的 JDBC 驱动。这时候直接在驱动设置里写一个自定义 Driver输入类名和 Jar 包路径DataGrip 就能识别。以 GoldenDB 为例它的 JDBC 连接串长这样jdbc:goldendb:loadbalance://10.208.225.135:8880/dbmarketadm?useUnicodetruecharacterEncodingutf8这个串一眼看过去和 MySQL 的很像但协议部分是jdbc:goldendb:不是jdbc:mysql:。你用 DataGrip 新建连接时如果默认列表里没有 GoldenDB就选Generic或手动添加驱动然后填这个 JDBC URL。驱动类一般是com.goldendb.Driver或兼容 MySQL 的com.mysql.cj.jdbc.Driver具体取决于你拿到的驱动包版本。连不上时优先检查驱动版本和数据库服务端版本是否兼容这是最常见的坑。2.3 迁移前的连接与权限检查清单在动手迁移之前我建议你花两分钟做一个快速巡检别等到迁移到一半才发现权限不够或者表结构对不上。我的固定检查项如下源库连接测试DataGrip 左下角的Test Connection必须绿绿完还要看驱动版本号避免连上的是旧协议导致类型映射异常。目标库连接测试同样要测试特别是目标库的存储引擎、字符集、大小写敏感配置要提前确认。源库账号权限至少要有SELECT、SHOW VIEW权限导出表结构和视图才能成功。如果要做整库迁移还要有读 information_schema 的权限。目标库账号权限至少要有CREATE、ALTER、INSERT、INDEX权限。生产环境建议用一个专门的迁移账号别拿 root 瞎搞。字符集对齐源库和目标库的字符集尽量保持一致。比如源库是utf8mb4目标库如果是latin1或者默认utf8中文数据导过去就会乱码或者报Incorrect string value错误。磁盘空间如果你走的是导出文件再导入的路线确认本地磁盘和目标库所在磁盘都有足够的空间。导出一个 20GB 的库文件可能膨胀到 25GB 以上因为 SQL 文本比二进制数据占空间。这六项确认完基本上后面的迁移操作就不会出幺蛾子了。3. 单表数据迁移最常用也最容易忽视细节3.1 通过导出文件实现单表迁移单表迁移是频率最高的操作。我举例一个场景你在生产库查了一波数据想导入到本地开发库做验证。两个库都能连DataGrip 里都配好了连接。步骤如下在源数据库的连接树里展开到目标表比如orders。右键表名选择Export Data to File...。弹出导出窗口选择导出格式。DataGrip 支持CSV、JSON、Excel、Insert Statement等格式。如果你的目标库是同一个数据库类型最推荐选择Insert Statement它会把数据生成一串INSERT INTO orders (...) VALUES (...)的 SQL 脚本你在目标库执行就能插进去。如果你的目标库是异构数据库推荐用CSV格式通用性最好。但要注意 CSV 的转义规则尤其是字段里包含逗号、换行、引号时DataGrip默认会用双引号包裹导入时也要按同样的规则解析。导出文件时有一个选项特别值得注意Include CREATE statement。勾选它DataGrip 会把你导出表的结构定义也带出来生成CREATE TABLE语句。这样到了目标库你直接把整个文件执行一遍建表和数据导入就都完成了。3.2 表对表直接传输DataGrip 的隐藏技能导出文件再导入中间多了一步文件传输。如果源库和目标库都同时配在 DataGrip 里其实可以跳过文件直接表对表传输。方法是在源库找到你要迁移的表直接按住表名拖到目标库的连接节点上松开鼠标DataGrip 会弹出一个窗口问你要怎么处理——是可以选择Copy Table或者类似的选项。这背后实际执行的操作是 DataGrip 读取源表的数据然后拼成 SQL 在目标库执行。如果在窗口里选择目标表不存在时自动建表它就会先根据源表结构生成CREATE TABLE再把数据 Insert 进去。这种方式对于百万行以内的表非常实用因为 DataGrip 会把数据分批提交。从实际操作来看速度比“导出再导入”要快不少。但注意表对表传输是走 JDBC 的数据量太大时会占用较多内存。我在传输一张 500 万行的表时DataGrip 的内存占用明显飙升如果你的机器配置一般建议限制一下行数或者改用文件导出方案。另外这个拖拽传输的方式还可以在同一个库里复制表。比如你想快速备份一张表直接右键表名选Duplicate Table就会生成一张带新名字的同结构表数据也会一并复制比写CREATE TABLE AS SELECT要直观得多。3.3 用 SQL 查询结果直接导出部分数据很多时候你不需要整张表的数据你只需要 “符合某些条件的若干行”。这时候单表全量导出就浪费了更合理的做法是先用 SQL 筛数据再导出。在 DataGrip 的查询控制台里写一条带条件的 SQL比如SELECT id, order_no, amount, created_at FROM orders WHERE created_at 2024-01-01 AND created_at 2024-04-01 AND status PAID;执行成功后查询结果会显示在下方的结果面板里。这时候你不需要把结果手动选中复制直接在结果区域右键选择Export Data to File...它导出的就是你当前查询出来的这批数据而不是整张表。这个操作非常实用。比如运营让你从生产库导出近三个月已支付订单给财务做对账你只要写好过滤条件导出 CSV 发给对方就行。注意 CSV 导出时可以选择Include column headers表头会带出来财务那边打开 Excel 直接就是带标题的表格。3.4 单表迁移中的字符集和日期格式避坑单表迁移看着简单但我在实际使用中踩过几个坑这里一次性说清楚中文乱码源库是utf8mb4导出 CSV 时如果没有在导出设置里选择 UTF-8 编码默认可能按系统字符集导出Windows 下就容易变 GBK 乱码。解决方法是导出时在File encoding里明确选UTF-8导入时也选同样的编码。日期格式漂移DataGrip 导出日期字段时默认格式是yyyy-MM-dd HH:mm:ss但如果源字段里带毫秒或时区信息导出到 CSV 可能丢精度。这时候需要用DATE_FORMAT先处理好再导出或者导出格式选 Insert Statement让 DataGrip 按数据库内部格式生成。自增主键冲突如果你导出的表有自增主键导入目标库时主键值也会一起插入。这就会导致目标库的自增计数器还是从 1 开始下次插入新数据时会主键冲突。我的习惯是导出时把自增主键列去掉让目标库重新分配或者导入后手动执行一次ALTER TABLE ... AUTO_INCREMENT 最大值1。大字段导出慢如果表里有TEXT、BLOB类型的字段导出时会比较慢因为每个大字段都要在内存里做 Base64 或转义处理。这种情况建议只在必要的时候导出这些字段临时去掉它们可以显著提速。4. 多表数据迁移选中一批表一起处理4.1 多选表的批量导出单表搞定了多表其实就是一个“批量”的概念。在 DataGrip 左侧的数据库树里你可以点住第一张表然后按住Ctrl键macOS 是Command逐个点击选中多张表也可以用Shift选中连续的一段表。选中之后右键任意一张被选中的表菜单里会出现Export Data to File...的选项。这个批量导出和单表导出的区别在于它会在同一个目录下为每张表生成独立的文件。比如你选中了users、orders、order_items三张表导出后会得到三个文件文件名默认就是表名后面跟着你选的格式后缀。批量导出时我强烈建议你保持“一张表一个文件”的方式而不是把所有表的数据塞进一个文件。原因很简单之后的导入如果出错单独的文件方便排查重导哪张就导哪张不用全部重来。4.2 用“Generate SQL Script”做多表结构同步多表迁移不只有数据结构变更也得带上。DataGrip 的Generate SQL Script功能就是为这个场景准备的。选中多张表后右键选择Generate SQL ScriptDataGrip 会生成一个包含所有选中表的CREATE TABLE语句和INSERT语句的脚本文件。你可以在生成时选择只生成 DDL结构或只生成 DML数据也可以两者都生成。这个功能的好处是生成的是一个标准 SQL 文件你拿到任何一个兼容 SQL 语法的目标库上都能执行。比如从 GoldenDB 导出几张表的结构拿到 MySQL 环境的 DataGrip 里直接跑绝大多数情况下都能成功。跨库类型的场景DataGrip 还会自动做类型转换虽然不是 100% 完美比如 Oracle 的VARCHAR2到 MySQL 的VARCHAR转换后长度可能超出预期但比起手写已经省力太多了。我在多表迁移中比较标准的流程是先在源库选好需要迁移的表。用Generate SQL Script生成一份 DDL 脚本在目标库先执行建表。再选中这些表做一次批量数据导出Insert Statement 格式。到目标库执行数据脚本。这种先结构后数据的方式比“一边建表一边导数据”要稳得多因为数据导入时表已经存在避免了很多临时表、外键约束的冲突问题。4.3 多表迁移时的外键顺序处理多表迁移有一个特别容易忽略的坑表之间的外键依赖关系。假设你要迁users和orders两张表orders表有一个外键指向users.id。如果你先把orders的数据插进去再插users那就会违反外键约束报Cannot add or update a child row错误。DataGrip 的Generate SQL Script在生成脚本时会尝试按照外键依赖关系给表排序但它只能保证“同一次生成的脚本”内有序。如果你手动分两次导数据就很容易踩到顺序坑。我的建议是有外键依赖的多表迁移优先用拖拽方式把所有选中的表一次性拖到目标库DataGrip 会处理顺序或者导出时直接不导外键约束迁移完成后再手动重建外键。后者更适合数据量大的场景因为带外键插入数据比不带外键慢不少。另外导入时还可以临时在目标库执行SET FOREIGN_KEY_CHECKS 0;等数据全部插入完毕后再执行SET FOREIGN_KEY_CHECKS 1;这个技巧在 MySQL 和兼容 MySQL 协议的数据库包括 GoldenDB上都有效迁移速度会有明显提升。5. 整库迁移一张不落地搬走5.1 整库迁移的两个层面结构 数据整库迁移听起来很唬人其实拆开就两层结构迁移和数据迁移。结构迁移就是把源库所有的表、视图、函数、存储过程、触发器等对象定义搬到目标库数据迁移就是把所有表里的数据搬过去。DataGrip 的整库迁移没有一个叫“一键整库迁移”的大按钮它是通过“全选所有表 批量处理”组合出来的能力。好处是粒度可控坏处是你需要理解每一层在做什么不能指望像 Navicat 的“数据传输”那样点两下全干完。但实际上DataGrip 的组合操作方式反而更灵活因为你可以在中间插入过滤条件、修改表名、调整数据类型这是很多一键工具做不到的。我的整库迁移标准流程是这样的连接源库和目标库。在源库连接树里点击数据库节点比如dbmarketadm。按CtrlA选中该库下的所有表。右键选择Generate SQL Script生成整个库的表结构脚本DDL。在目标库 DataGrip 控制台执行这个 DDL 脚本。回到源库再次全选所有表使用拖拽方式把整库数据传到目标库或者通过批量导出的方式先导出文件再去目标库导入。5.2 整库拖拽迁移的操作细节与速度优化全选所有表后拖到目标库连接节点上DataGrip 会弹出一个迁移窗口。这个窗口里有一些选项值得注意Batch size批量大小每次提交多少行数据。默认可能是 500 或 1000如果你目标库性能不错可以适当调大到 2000~5000速度会有明显提升。但如果目标库是低配的测试环境调太大反而会把目标库打满造成锁等待。On duplicate key主键冲突时怎么办可选Update或Ignore等策略。如果你迁过去的目标库表里已经有一部分数据这次是想补齐全量选Update会更合适如果是全新的空库默认行为就好。Create table if not exists如果目标库的表不存在是否自动建表。第一次迁移建议勾上后面重复迁移时可以去掉避免结构被覆盖。整库迁移有个物理限制不得不提前说DataGrip 是 JDBC 逻辑迁移不是物理文件拷贝。这意味着它的速度上限受限于 JDBC 的INSERT执行效率。对于几千张表、总量几个 GB 的库它可能需要跑几十分钟甚至更久对于十几个 TB 的大库我不建议用 DataGrip 整库搬还是上物理备份恢复或者数据泵方案更现实。我实测过一个 2GB 左右、包含 300 多张表的 MySQL 库DataGrip 拖拽迁移大概跑了 25 分钟左右。这个速度对于逻辑迁移来说算正常。如果你觉得慢可以把Batch size调到 5000同时建议把目标库的innodb_flush_log_at_trx_commit临时改为0或2注意这有数据安全风险只适合迁移这种可重建场景迁移完再改回来提速非常明显。5.3 视图、函数和触发器的迁移方案DataGrip 的表结构生成能力很成熟但视图、函数、存储过程、触发器这类对象它的图形界面支持就弱一些。整库迁移时这一块需要单独处理。我常用的方法是在源库 DataGrip 控制台执行类似下面的 SQL把视图定义查出来以 MySQL 为例SELECT TABLE_NAME, VIEW_DEFINITION FROM information_schema.VIEWS WHERE TABLE_SCHEMA 源库名;或者直接右键数据库节点选择Generate SQL Script时DataGrip 在某些版本里支持连视图一起生成。如果你的版本不支持就手动查出来复制到目标库执行。函数、存储过程的迁移更麻烦一点因为不同数据库的语法差异较大。DataGrip 右键函数名时可以选Generate SQL Script单对象生成但批量生成整个库的函数暂不支持得很好。这块最稳妥的方案还是把源库的对象手动导出成 SQL 文件再用 DataGrip 打开执行。对于触发器我建议在数据迁移完成之后再去目标库创建因为触发器可能会在数据插入过程中被触发如果触发的逻辑引用了还没迁完的表会产生一堆诡异的报错。5.4 整库迁移后的一致性校验数据搬完了怎么确认没丢数我的做法是对比行数。在 DataGrip 里针对每个库执行一遍统计行数的 SQL以 MySQL/GoldenDB 为例可以生成统计所有表行数的语句SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema 目标库名;但注意table_rows是估算值不是精确值。更靠谱的做法是逐表执行SELECT COUNT(*)或者用 DataGrip 的Compare功能把源库和目标库的连接都展开选中同一个库名右键选择CompareDataGrip 会列出哪些表缺失、哪些表结构不一致、哪些表行数不一致。这个对比结果虽然不是 100%精确到行级但用来做迁移验收已经够用了。我迁移完通常会做三层校验表数量是否一致。每张表的行数是否一致。抽几张关键业务表对比一些关键字段的汇总值比如订单总金额、用户总数。三层校验都通过整库迁移基本就可以宣布成功。6. 常见问题与排查技巧实录6.1 驱动加载失败或连接超时现象新建连接时提示Cannot load driver class或者测试连接一直转圈然后超时。排查思路如果是自动下载驱动失败切到手动添加本地 Jar 包。如果是驱动类名不匹配确认 JDBC URL 里的协议和 Driver 类名是否对得上。GoldenDB 这类走 MySQL 协议的有时你换用 MySQL 驱动反而能连上但功能上有一些差异最好是找对专用驱动。连接超时先 ping 一下数据库 IP确认网络通不通再 telnet 一下端口比如telnet 10.208.225.135 8880看数据库端口是否对外开放。很多时候不是 DataGrip 的问题而是防火墙挡了。6.2 导入时中文乱码现象数据导过去之后中文显示成???或者一堆乱码。排查思路检查源表和目标表的字符集是否一致。不一致时以目标表字符集为准必要时导出前先CONVERT一下。检查 CSV 文件的编码设置。Windows 下 DataGrip 可能默认 GBK改成 UTF-8 就好。检查 JDBC URL 里是否带characterEncodingutf8参数。MySQL 和 GoldenDB 的连接串里这个参数非常关键。如果用的是 Insert Statement 导入检查控制台连接的会话字符集执行前先SET NAMES utf8mb4;。6.3 导出时内存溢出或卡死现象导出大表时 DataGrip 卡顿甚至报OutOfMemoryError。排查思路调整 DataGrip 的 JVM 堆内存。JetBrains 系产品可以在 Help - Change Memory Settings 里调大比如设置为 2048MB 或更高。大表导出不要一次性全量导先用 SQL 分批导出按主键范围或者按日期分成多个小文件。关闭不必要的数据库连接和结果集缓存。DataGrip 默认会在结果面板缓存查询结果大结果集会吃内存。导出大量数据时优先用右键表的Export Data而不是SELECT *后再导出因为前者走的是流式读取后者会把结果先加载到内存。6.4 目标表字段类型映射不对现象比如源库是tinyint(1)目标库变成了boolean源库是decimal(10,2)目标库变成了double精度有损失。排查思路这类问题在异构库迁移时比较常见。DataGrip 会按内置的映射规则转换字段类型但它不知道你的业务意图。解决办法是在拖拽迁移的窗口里先选择Create table然后把生成的建表语句手动检查一遍对关键字段的类型做调整再执行建表和导入。如果是通过Generate SQL Script生成的 DDL直接编辑脚本把类型改对再在目标库执行。6.5 迁移中断无法续跑现象几百万行的表传到一半网络断了或者目标库报了个错整个迁移失败需要重头再来。排查思路先确认目标库里已经插入了多少数据如果断点前的数据已经提交可以先清空这张表再重新导。DataGrip 的拖拽迁移不支持断点续传所以大数据量表建议先导结构再分批导数据。比如按主键范围分成几段-- 第一段 SELECT * FROM orders WHERE id BETWEEN 1 AND 1000000; -- 第二段 SELECT * FROM orders WHERE id BETWEEN 1000001 AND 2000000;每段导完确认成功再导下一段。还有一种更省事的方式用 DataGrip 的Trigger-based synchronization或第三方同步工具但这些超纲了日常分批导入其实最实用。6.6 大小写表名导致的找不到表现象源库有Users表导到目标库后变成users或者反过来报Table xxx.users doesnt exist。排查思路这是 Linux 上 MySQL/GoldenDB 的大小写敏感配置导致的lower_case_table_names参数不同表现就不同。在目标库建表前先在 DataGrip 的 DDL 脚本里把表名统一成目标库需要的大小写规则。如果已经导完了才发现问题最简单的办法是在目标库建一个同义词或视图兼容或者重新执行一次RENAME TABLE。6.7 大字段和二进制数据导入报错现象表里有BLOB、LONGBLOB字段插入时提示Data truncation或者Packet too large。排查思路调大目标库的max_allowed_packet参数。MySQL 默认可能是 4MB如果一条记录里有一个几 MB 的图片或者文件二进制就会超限报错。如果是批量导入建议把Batch size调小一些比如一次 100 条避免单次提交的数据量过大。7. 迁移完成后我习惯做的几件事数据迁移完成后不是看一眼“表都在”就结束了。我个人的习惯是三件套每次迁移完都照做省了不少回头麻烦。先把目标库的统计信息刷新一遍。MySQL、GoldenDB 这类数据库的表行数是估算值迁移完成后执行ANALYZE TABLE或OPTIMIZE TABLE更新统计信息优化器才能走正确的执行计划否则你后续查一张大表会发现索引生效得不理想。然后检查自增主键的后续值。DataGrip 迁移数据时会把主键 ID 原样带过去但目标表的AUTO_INCREMENT计数器可能还停留在 1。如果不在迁移后手动改掉下次业务插入新数据时轻则主键冲突重则覆盖已有数据。修正方式很简单ALTER TABLE orders AUTO_INCREMENT 100001;把起始值设成当前表内最大值加一。最后是权限和账号的核对。有些数据库的视图、函数在迁移时会依赖特定的用户权限如果目标库的账号权限和源库不一致业务侧可能能查表但一调用存储过程就报权限错误。迁移完我会逐个检查存储过程、触发器的DEFINER确保它们指向目标库实际存在的账号。这三件事每次花不了五分钟但能帮你把迁移从“数据搬完了”推进到“业务可以正常跑”的状态。最后再分享一个我个人的小技巧如果你是经常在多个环境之间搬数据可以在 DataGrip 里把常用迁移的源库和目标库放到同一个Group文件夹下这样每次拖拽迁移连找连接都省了展开就是干。配合 DataGrip 的Compare功能连迁移前后校验也一起顺手做了。工具这东西用熟了是真的能省下大量重复劳动。