统一走CSV中间格式:PostgreSQL用COPY导出,MySQL预建表并降级类型,CSV预处理NULL;Windows计划任务需显式指定Python路径并安装依赖;Linux管道迁移应改用临时文件避免超时截断。
用 pg_dump + mysqlimport 做 PostgreSQL → MySQL 迁移时,字段类型不匹配怎么办
直接导出再导入大概率失败,因为 pg_dump --format=plain 生成的是 sql,而 mysqlimport 只认 csv;反过来用 mysqldump --tab 导出的 csv,postgresql 的 copy 又可能因空值、转义符报错。
真正能落地的做法是统一走文本中间格式,且主动控制类型映射:
- 从 PostgreSQL 导出用
psql -c "COPY (SELECT ... ) TO STDOUT WITH CSV HEADER",避免pg_dump的 DDL 干扰 - 对 MySQL 目标表提前建好,字段类型按需降级:比如
timestamp with time zone改成datetime,jsonb转成text - 导出 CSV 后用
sed或awk预处理:把 PostgreSQL 的NULL字面量(\N)替换成空字符串,否则mysqlimport会当成字面值插入
Windows 计划任务调用 Python 脚本执行跨库迁移,为什么总提示 ModuleNotFoundError: No module named 'psycopg2'
计划任务默认使用系统环境,和你命令行里激活的虚拟环境不是一回事。哪怕脚本开头写了 #!/usr/bin/env python3,Windows 也不认这行。
必须显式指定解释器路径,并确保依赖在该环境下安装:
- 在计划任务操作中,“程序或脚本”填绝对路径,例如:
C:\Python39\python.exe - “添加参数”填脚本路径:
C:\etl\migrate.py -
psycopg2和PyMySQL必须装在C:\Python39对应的 site-packages 下,不能只装在 venv 里 - 如果用的是二进制分发版(如
psycopg2-binary),确认 Windows 架构匹配:x64 Python 不能用 x86 的 DLL
Linux 下用 crontab 跑 mysqldump → psql 管道迁移,数据中途截断
典型现象是日志显示 “Killed” 或 “Broken pipe”,不是语法错,而是 crontab 默认限制进程内存和超时,管道一卡就全崩。
关键不是改 SQL,而是绕过管道,用临时文件做缓冲:
- 别写
mysqldump ... | psql ...,改用两步:mysqldump ... > /tmp/latest.sql,再psql ... - 在 crontab 条目前加环境变量:
SHELL=/bin/bash; PATH=/usr/local/bin:/usr/bin:/bin,否则mysqldump可能找不到 - 加
timeout -s SIGTERM 1800控制单次最长执行时间,防止锁表太久 - 记得清理
/tmp/latest.sql,不然磁盘迟早满
异构迁移脚本里硬编码数据库密码,CI/CD 流水线里怎么安全传参
把密码写进脚本或命令行参数,日志一打出来就全暴露。环境变量看似方便,但 ps aux 能直接看到启动命令里的值。
生产可用的最低成本方案是用配置文件 + 文件权限隔离:
- 创建
/etc/db-creds.conf,内容为PGPASSWORD=xxx MYSQL_PWD=yyy,属主设为运行用户,权限600 - 脚本开头用
source /etc/db-creds.conf(bash)或set -o allexport; source /etc/db-creds.conf; set +o allexport - 如果必须用 Python,改用
getpass.getpass()交互式输入——但计划任务里不行,所以只能回到文件方案 - 切记不要用
.env文件放密码,它容易被 git 提交或 Web 服务意外暴露
跨库迁移真正的麻烦不在语法,而在两边对 NULL、时区、自动递增、字符集的理解根本不一致。每次换目标库,都要重验一遍字段映射和边界值,没捷径可抄。










