Linux下pgloader 3.6.9安装避坑指南:从依赖缺失到编译成功
最近在折腾一个数据库迁移项目,需要把几个老旧的MySQL实例里的数据,规整地搬到PostgreSQL里。市面上工具不少,但论灵活性和对复杂数据类型的支持,pgloader一直是我的首选。它用Common Lisp写成,性能强悍,配置也足够直观。不过,它的安装过程,尤其是从源码编译,对不少朋友来说可能是个“劝退”环节。我这次在CentOS 7和Ubuntu 20.04上都走了一遍,把从下载到成功运行过程中踩的坑、绕的路,以及最终找到的“捷径”都梳理了出来。这份指南不只是步骤的罗列,更侧重于解释为什么会出错,以及如何系统性地解决依赖问题,目标是让你下次再遇到类似编译问题,能自己举一反三。
1. 环境准备与依赖全景图
在动手敲下第一个命令之前,花几分钟理解pgloader的依赖生态,能省下后面几小时的折腾时间。pgloader本质上是一个用Common Lisp编写的应用程序,它通过make系统来驱动构建过程。这个构建过程并不像普通的C程序那样简单./configure && make,它更像是在搭建一个微型的Lisp运行时环境,并在这个环境中编译出最终的可执行二进制文件。
因此,它的依赖可以分为三个层次:
- 构建系统依赖:即
make、gcc等基础编译工具链。 - Lisp运行时依赖:核心是SBCL (Steel Bank Common Lisp),它是
pgloader的“编译器”和“运行时”。没有它,构建过程根本无法启动。 - 数据库客户端库依赖:这是
pgloader实现其核心功能——连接各种数据源——所必需的。例如:- libsybdb / FreeTDS:用于连接SQL Server和Sybase数据库。
- MySQL客户端库:用于连接MySQL/MariaDB。
- SQLite3库:用于连接SQLite数据库。
- PostgreSQL客户端库 (libpq):用于连接目标PostgreSQL数据库(这个通常系统已装)。
很多安装失败,都源于对第二层和第三层依赖的不了解或遗漏。下面这个表格帮你快速理清主流Linux发行版上需要安装的包:
| 依赖类别 | CentOS / RHEL / Rocky Linux / AlmaLinux (使用 yum) | Ubuntu / Debian (使用 apt) | 作用说明 |
|---|---|---|---|
| 构建工具 | make gcc git patch unzip | make gcc git patch unzip | 基础编译环境。 |
| Lisp运行时 | sbcl (需通过EPEL仓库) | sbcl | 核心依赖,提供Common Lisp编译环境。 |
| 数据库客户端库 | freetds-devel mariadb-devel sqlite-devel postgresql-devel openssl-devel | freetds-dev libmariadb-dev libsqlite3-dev libpq-dev libssl-dev | 使pgloader能够连接各类源数据库。名称后缀-devel或-dev代表开发头文件,必须安装。 |
提示:在生产服务器上操作前,建议先在测试环境完整走一遍流程。如果服务器无法连接外网,你需要提前下载好所有依赖包的RPM或DEB文件进行离线安装,这会复杂很多。
对于CentOS系列,首先需要确保EPEL(Extra Packages for Enterprise Linux)仓库已启用,这是获取sbcl等软件的关键:
# CentOS/RHEL 7/8
sudo yum install -y epel-release
# 或者 Rocky/AlmaLinux 8+
sudo dnf install -y epel-release
然后,可以一次性安装大部分开发依赖(以CentOS为例):
sudo yum groupinstall -y "Development Tools"
sudo yum install -y sbcl freetds-devel mariadb-devel sqlite-devel postgresql-devel openssl-devel git unzip
对于Ubuntu/Debian系列,步骤更直接:
sudo apt update
sudo apt install -y make gcc sbcl freetds-dev libmariadb-dev libsqlite3-dev libpq-dev libssl-dev git unzip
完成上述步骤,你的系统才算是为编译pgloader做好了“热身”。这步做扎实了,后续的报错会少一大半。
2. 获取源码与解压的艺术
官方推荐的安装方式是使用打包好的pgloader-bundle。这个Bundle非常贴心,它已经包含了pgloader本身及其所有Lisp语言的依赖项(如quicklisp包管理器、cffi、cl+ssl等),避免了你在构建过程中还需要联网下载Lisp库的麻烦,对于内网环境尤其友好。
下载和解压本身很简单,但有几个细节值得注意:
# 1. 使用wget或curl下载Bundle包
wget https://github.com/dimitri/pgloader/releases/download/v3.6.9/pgloader-bundle-3.6.9.tgz
# 或者
curl -L -o pgloader-bundle-3.6.9.tgz https://github.com/dimitri/pgloader/releases/download/v3.6.9/pgloader-bundle-3.6.9.tgz
# 2. 解压到当前目录
tar -zxvf pgloader-bundle-3.6.9.tgz
# 3. 进入解压后的目录
cd pgloader-bundle-3.6.9
进入目录后,你会看到类似这样的结构:
pgloader-bundle-3.6.9/
├── bin/
├── build/
├── local-projects/ # 这里包含了pgloader的源码
│ └── pgloader-3.6.9/
├── Makefile
├── patches/
└── ... (其他配置和依赖文件)
注意:整个构建过程都将在
pgloader-bundle-3.6.9目录内完成,不要尝试进入local-projects/pgloader-3.6.9/子目录去执行make,那样会失败。顶层的Makefile是统筹整个构建流程的入口。
3. 编译过程详解与排错实战
现在来到核心环节:执行make pgloader。这个过程可能会一帆风顺,更可能会遇到几个经典的错误。我们逐一拆解。
3.1 第一关:SBCL缺失
这是最常遇到的第一个错误。
$ make pgloader
...
make: sbcl: Command not found
Makefile:30: recipe for target 'bin/pgloader' failed
make: *** [bin/pgloader] Error 127
错误解读:make脚本试图调用sbcl命令来启动Lisp编译环境,但系统里找不到这个命令。
解决方案:正如我们在第一章准备的,安装sbcl。请根据你的发行版选择命令。安装后,可以通过sbcl --version验证。
深入一点:为什么一定是SBCL?因为pgloader的Bundle和Makefile就是为SBCL优化的。Common Lisp有其他实现(如CLISP),但兼容性和性能可能有问题,不推荐替换。
3.2 第二关:数据库客户端库缺失(以FreeTDS为例)
安装好sbcl后再次make,很可能遇到第二个坎:
$ make pgloader
...
Unhandled CFFI:LOAD-FOREIGN-LIBRARY-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1001870103}>:
Unable to load foreign library (LIBTDSODBC).
Error opening shared object "libsybdb.so.5":
libsybdb.so.5: cannot open shared object file: No such file or directory.
错误解读:Lisp代码在编译时,通过CFFI(Common Foreign Function Interface)尝试加载一个名为libsybdb.so.5的C语言动态链接库。这个库是FreeTDS项目的一部分,用于连接SQL Server/Sybase。系统找不到这个库文件。
解决方案:安装FreeTDS的开发包。注意,只安装freetds可能不够,因为它可能只包含运行时库。我们需要的是包含libsybdb.so链接和头文件的开发包。
- CentOS:
sudo yum install -y freetds-devel - Ubuntu:
sudo apt install -y freetds-dev
安装后,关键的库文件通常会在/usr/lib64/或/usr/lib/x86_64-linux-gnu/下出现(例如libsybdb.so.5)。
类似问题:如果你未来需要从MySQL迁移数据,但没装MySQL客户端库,可能会看到找不到libmariadb.so或libmysqlclient.so的错误。同理,需要安装mariadb-devel或libmariadb-dev。
3.3 第三关:其他潜在依赖问题
解决了上述两个主要问题,编译通常就能成功了。但如果你的环境比较“干净”,还可能遇到:
- OpenSSL库缺失:错误信息可能提及
libssl.so或libcrypto.so。确保安装了openssl-devel(CentOS)或libssl-dev(Ubuntu)。 - SQLite库缺失:如果你需要加载SQLite文件。安装
sqlite-devel或libsqlite3-dev。 - 内存不足:SBCL在编译大型Lisp项目时可能消耗较多内存。如果是在小内存的VPS或容器内编译,可能会失败。尝试增加交换空间(swap):
# 创建一个2GB的交换文件(如果已有可跳过) sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 编译完成后,可以关闭并删除:sudo swapoff /swapfile && sudo rm /swapfile
3.4 编译成功与验证
当所有依赖都满足后,再次运行make pgloader,你会看到大量Lisp编译信息滚动,最后以类似下面的信息结束:
...
;; loading system "pgloader"
compressed 0 bytes into 8 at level -1
compressed 32768 bytes into 630 at level -1
...
compressed 131792896 bytes into 20821046 at level -1
that's ugly, but necessary when building on Windows :(
mv bin/pgloader.tmp bin/pgloader
看到最后一行mv命令执行,并且没有红色错误信息,就说明编译成功了!此时在./bin/目录下会生成一个名为pgloader的独立二进制文件。
你可以立即在当前目录测试它:
./bin/pgloader --version
如果输出类似pgloader version "3.6.9",那么恭喜你,最艰难的部分已经过去了。
4. 安装、配置与基础使用
编译出的pgloader二进制文件是自包含的,你可以把它放在任何地方运行。但为了使用方便,通常我们会把它安装到系统的标准路径下。
4.1 安装到系统路径
# 将pgloader复制到/usr/local/bin,这是存放用户级可执行程序的常见位置
sudo cp ./bin/pgloader /usr/local/bin/
# 验证安装
pgloader --version
现在,你可以在系统的任何位置直接使用pgloader命令了。
4.2 编写你的第一个迁移命令文件
pgloader的强大之处在于其声明式的命令文件。它比单纯用命令行参数更清晰、可重复。假设我们要从本地的MySQL数据库source_db迁移my_table到PostgreSQL的target_db。
创建一个文件,例如migrate.load:
# migrate.load
LOAD DATABASE
FROM mysql://username:password@localhost/source_db
INTO postgresql://username:password@localhost/target_db
WITH include drop, create tables, create indexes, reset sequences,
workers = 8, concurrency = 1,
multiple readers per thread, rows per range = 50000
CAST type datetime to timestamptz drop default drop not null using zero-dates-to-null,
type date drop default drop not null using zero-dates-to-null
MATERIALIZE VIEWS my_view1, my_view2
INCLUDING ONLY TABLE NAMES MATCHING 'my_table', 'another_table'
;
这个命令文件做了几件事:
FROM/INTO:定义数据源和目标。WITH:设置加载行为,如删除目标表、并行 workers 数等。CAST:处理类型转换,这里将MySQL的datetime和date类型中的0000-00-00零值转换为PostgreSQL的NULL。MATERIALIZE VIEWS:将MySQL的视图作为表迁移到PostgreSQL。INCLUDING ONLY TABLE NAMES MATCHING:只迁移指定的表,支持通配符。
4.3 执行迁移
运行迁移命令非常简单:
pgloader migrate.load
pgloader会启动,解析命令文件,建立连接,然后开始迁移。它会输出详细的日志,包括每个步骤的耗时、数据行数、可能出现的警告等。迁移结束后,务必仔细查看输出的总结报告,确认没有失败的表或严重的类型转换错误。
4.4 性能调优与常见参数
对于大数据量迁移,几个参数对性能影响很大:
workers:设置并行加载的工作进程数。通常可以设置为CPU核心数。concurrency:控制从源数据库读取数据的并发线程数。对于MySQL,设置为1通常更稳定;对于文件(如CSV),可以增加。batch rows:每个批次插入的行数。默认是25000,如果内存充足,可以适当增加(如50000)以提高吞吐。prefetch rows:预取的行数。增加此值可以提高读取速度,但会增加内存使用。
一个针对大数据量优化的WITH子句可能长这样:
WITH include drop, create tables, create indexes, reset sequences,
workers = 8, concurrency = 1,
batch rows = 50000, batch size = 50 MB,
prefetch rows = 100000,
multiple readers per thread, rows per range = 100000
5. 进阶场景与故障排查
5.1 从CSV文件加载
pgloader处理CSV文件同样出色。假设有一个data.csv文件,第一行是列名。
# csv.load
LOAD CSV
FROM 'path/to/data.csv' (field1, field2, field3)
INTO postgresql:///target_db?tablename=target_table
TARGET COLUMNS (col1, col2, col3)
WITH skip header = 1,
fields terminated by ',',
fields optionally enclosed by '"',
fields escaped by double-quote,
truncate,
batch rows = 10000;
5.2 处理迁移中的错误
迁移很少能一次完美成功。pgloader默认会在遇到第一个错误时停止。你可以修改这个行为:
WITH ...,
on error stop, -- 默认值,遇到错误停止
-- 或者
on error resume next -- 跳过错误行,继续执行(需谨慎!)
更推荐的做法是使用--verbose和--debug选项运行,将详细日志输出到文件进行分析:
pgloader --verbose --debug migrate.load 2>&1 | tee migration.log
常见的错误包括:
- 连接失败:检查数据库URL、网络、防火墙、用户权限。
- 数据类型不兼容:仔细检查
CAST规则,可能需要自定义转换函数。 - 外键或唯一约束冲突:确保源数据是干净的,或者调整加载顺序(先加载父表,再加载子表)。
5.3 使用Docker绕过安装难题
如果你觉得编译安装太麻烦,或者需要在不同环境快速使用,Docker是最推荐的替代方案。官方提供了pgloader的Docker镜像,开箱即用。
# 拉取最新镜像
docker pull dimitri/pgloader:latest
# 运行一个简单的迁移(假设命令文件在当前目录)
docker run --rm -v $(pwd):/data dimitri/pgloader:latest pgloader /data/migrate.load
# 更复杂的例子:允许容器访问宿主机的数据库网络
docker run --rm --network host -v $(pwd):/data dimitri/pgloader:latest pgloader /data/migrate.load
Docker方式几乎免除了所有依赖安装的烦恼,特别适合在CI/CD流水线或临时环境中使用。镜像内已经包含了所有必需的数据库客户端库。
编译安装pgloader的过程,像是一次对开源软件依赖管理的微型实习。它教会你的不仅仅是几条命令,更是一种排查思路:当编译失败时,首先看错误信息,定位缺失的库或命令;然后理解这个库属于哪个层次(构建工具、运行时、功能库);最后利用系统包管理器精准安装。掌握了这个方法,今后面对任何从源码编译的软件,你都能更有底气。至于选择编译安装还是Docker,我的建议是,如果你需要深度定制或研究其代码,那就编译;如果只是作为工具使用,Docker镜像无疑是更高效、更干净的选择。
380



被折叠的 条评论
为什么被折叠?



