在多数据源并存的企业环境中,常常需要在不同数据库之间进行联合分析或数据迁移。PostgreSQL 作为功能强大的开源关系型数据库,提供了 Foreign Data Wrapper(FDW,外部数据包装器)机制,允许它像访问本地表一样查询远程数据库。

本文将手把手带你配置 mysql_fdw,实现 PostgreSQL 对 MySQL 表的透明读写访问,真正做到“一处查询,跨库联动”。
mysql_fdw 是一个 PostgreSQL 的 FDW 扩展,由 EnterpriseDB 开发并开源。它通过 MySQL 客户端库(libmysqlclient)连接远程 MySQL 实例,并将远程表映射为 PostgreSQL 中的“外部表”(Foreign Table)。你可以在 PostgreSQL 中直接对这些外部表执行 SELECT、INSERT、UPDATE、DELETE 等操作(取决于权限和配置)。
✅ 适用场景:
- 实时报表聚合(PG + MySQL 联合查询)
- 数据迁移过渡期
- 微服务间临时数据打通
- 避免 ETL 中间层,简化架构
# 安装编译工具和 PostgreSQL 开发包sudo apt updatesudo apt install build-essential postgresql-server-dev-all libmysqlclient-dev git# 克隆 mysql_fdw 源码(官方 GitHub)git clone https://github.com/EnterpriseDB/mysql_fdw.gitcd mysql_fdw
⚠️ 注意:确保 libmysqlclient-dev 版本与目标 MySQL 兼容。若使用 MySQL 8.0,可能需额外处理认证插件(如 caching_sha2_password)。
# 编译(自动检测 pg_config)make# 安装到 PostgreSQL 扩展目录sudo make install
验证是否安装成功:
# 查看 PostgreSQL 的 extension 目录pg_config --sharedir# 应能在 $SHAREDIR/extension/ 下看到 mysql_fdw.control 和 .so 文件
以 postgres 用户登录 psql:
-- 创建扩展(每个需使用的数据库都要执行)CREATE EXTENSION mysql_fdw;
CREATE SERVER mysql_serverFOREIGN DATA WRAPPER mysql_fdwOPTIONS ( host '192.168.1.100', -- MySQL 主机 IP port '3306' -- MySQL 端口);
将 PostgreSQL 用户映射到 MySQL 的认证凭据:
CREATE USER MAPPING FOR postgres -- PostgreSQL 本地用户SERVER mysql_serverOPTIONS ( username 'remote_user', password 'secure_password');
? 安全建议:避免在 SQL 中明文写密码,可结合
.pgpass或 Vault 等密钥管理工具。
假设 MySQL 中有数据库 sales_db,表 orders 结构如下:
-- MySQL 表结构示例CREATE TABLE orders ( id INT PRIMARY KEY, customer_name VARCHAR(100), amount DECIMAL(10,2), created_at DATETIME);
在 PostgreSQL 中创建对应的外部表:
CREATE FOREIGN TABLE foreign_orders ( id INTEGER, customer_name TEXT, amount NUMERIC(10,2), created_at TIMESTAMP)SERVER mysql_serverOPTIONS ( dbname 'sales_db', table_name 'orders');
? 注意:
- 字段名必须一致(大小写敏感)
- 类型需兼容(MySQL 的 VARCHAR → PG 的 TEXT,DATETIME → TIMESTAMP)
- 不支持所有 MySQL 特有类型(如 JSON 需测试)
SELECT * FROM foreign_orders WHERE amount > 1000;
SELECT u.name, o.amountFROM local_users uJOIN foreign_orders o ON u.mysql_order_id = o.id;
INSERT INTO foreign_orders (id, customer_name, amount, created_at)VALUES (1001, 'Alice', 1500.00, NOW());UPDATE foreign_orders SET amount = 1600 WHERE id = 1001;DELETE FROM foreign_orders WHERE id = 1001;
⚠️ 警告:写操作会直接修改 MySQL 数据,请谨慎使用!
bind-address)GRANT SELECT, INSERT... ON sales_db.* TO 'remote_user'@'%'MySQL 8 默认使用 caching_sha2_password,而旧版 libmysqlclient 可能不支持。
解决方案:
libmysqlclient-dev 到 8.0+CREATE USER 'remote_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
| 方案 | 优点 | 缺点 |
|---|---|---|
| mysql_fdw | 实时、SQL 透明、支持读写 | 依赖 libmysqlclient,部署复杂 |
| 逻辑复制 + ETL | 稳定、可控 | 延迟高,需维护管道 |
| dblink(不支持 MySQL) | — | PostgreSQL 原生 dblink 仅支持 PG |
通过 mysql_fdw,PostgreSQL 成功打破了与 MySQL 的数据孤岛。虽然它不适合高并发写入或超大规模分析场景,但在开发调试、轻量级集成、临时数据桥接等场景中极具价值。