从 MySQL 中导出数据
忽略表结构(因为我会一开始就在 pg 中创建好)
mysqldump -h <mysql host> -u <mysql user> --password=<mysql password> <mysql database> \
--skip-disable-keys --skip-add-locks \
--no-create-info --skip-add-drop-table \
--set-gtid-purged=OFF --skip-set-charset \
--where="created_time < '2025-10-01 00:00:00'" \
<table name> > xxxx.sql
解释:
--password=<mysql password>:指定对应的密码。注意:在命令行输入密码有一定的安全风险,通常建议不写在命令行中,让 mysqldump 提示输入,正常情况下应该写-p--skip-disable-keys:导出数据时不会在导入时禁用和启用索引,适合导入较快,但可能导致导入期间索引不可用。--skip-add-locks:不在导出中包含锁表的 SQL 语句,加快导出速度。PS:不知道是不是真的有用,反正我看到生成的 SQL 还是有的--no-create-info:只导出数据(INSERT 语句),不导出表结构(不包含 CREATE TABLE),适合只需要某些数据。--skip-add-drop-table:不在导出中加入 DROP TABLE 语句,避免删除已有表。--set-gtid-purged=OFF:控制是否输出 GTID 相关的语句(在集群环境中使用),这里关闭(不输出)GTID 信息。--skip-set-charset:不加入设置字符集的相关语句,保持导出文件的简洁。--where=:只导出满足条件的行
导出的内容大致如下:
-- MySQL dump 10.13 Distrib 8.4.7, for Linux (x86_64)
--
-- Host: xxxxx Database: xxxx
-- ------------------------------------------------------
-- Server version 8.0.28
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Dumping data for table `xxxxx`
--
INSERT INTO `xxxx` VALUES (xxxx),(xxxx),(xxxxx),(xxxx);
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-10-31 3:45:10
可以注意到他会把很多表的数据集中在一条语句中插入,好像上面哪个选项去掉之后就会变成一条记录一个 insert 语句,但是我比较喜欢当前这样
如果记录实在是太多,一条 insert 也会写不完,会有多条 insert 语句的
导入 PostgreSQL
处理反引号
PostgreSQL 不支持反引号,还好这里只是表名有反引号,所以用 sed 命令去除即可
sed -i 's/`<表名>`/<表名>/g' xxxx.sql
时区
注意 MySQL 的 datetime 是不带时区的,而 PostgreSQL 的 timestamptz 是带时区的,因此要注意一下(我当前因为 MySQL 和 pg 的时区都是 Shanghai 所以还好)
string 类型
- 字符串中的单引号(’):PostgreSQL 默认不支持反斜杠转义单引号,正确做法:用两个单引号
''来表示单引号 - 字符串中的双引号("):PostgreSQL 并不需要对双引号进行转义,且字符串是用单引号括起来的,双引号在字符串里是普通字符,不需要转义
- 字符串中的反斜杠(\):PostgreSQL 关于反斜杠的处理说明:
- 默认情况下,PostgreSQL 的字符串不支持反斜杠作为转义符,除非开启了 standard_conforming_strings = off,否则反斜杠会被当作普通字符处理。
- 但是如果你要在字符串中插入反斜杠字符,直接写一个反斜杠即可。如果写两个反斜杠,会被解析成两个反斜杠。
- 比如如果想插入该表情字符
¯\_(ツ)_/¯,正确写法: - 直接写一个反斜杠即可:
'¯\_(ツ)_/¯' - 如果你使用的是标准字符串字面量,且没有关闭标准符合字符串,建议写成:
E'¯\\_(ツ)_/¯',这里的 E 表示启用 C 风格转义,两个反斜杠\\被转义成一个反斜杠。
最后我为了简单,直接在会话的维度开启
standard_conforming_strings = off:SET standard_conforming_strings TO off;所以我先登录到 pg 的控制台,执行上面的语句开启反斜杠的转义字符功能之后,执行
\i <mysql insert sql file>来执行数据导入