mysql_fdw 使用手册

1 概述

mysql_fdw 用于让 UDB 通过 MySQL 客户端库访问 MySQL 数据库,并把 MySQL 的表(或查询结果)映射为 UDB 内可查询的外部表。

工作链路:

SQL 查询
  → UDB 服务进程
    → mysql_fdw
      → libmysqlclient
        → MySQL 服务器

交付包通常已包含 mysql_fdw 扩展文件;正常情况下无需额外准备,只需在 ud_sql 中创建扩展、创建外部服务器与外表即可使用。若连接失败,再参考本文“连接失败排查”。

2 快速开始

2.1 前提

  • UDB 服务已启动,ud_sql 可正常进入(例如 unvdb=#)。

  • 目标 MySQL 可访问(网络可达、账号具备权限)。

路径约定(示例,按现场替换):

  • <安装包目录>:UDB 安装/解压目录,例如 /home/unvdb/work/UDB-TX-26

  • <数据目录>:UDB 数据目录,例如 /home/unvdb/work/unvdb-data

  • 环境变量推荐写入:<数据目录>/env.sh,并在启动服务前 source 使其对服务进程生效

2.2 最小可用 SQL(复制后替换占位符)

占位符说明:

  • <mysql_host>:MySQL 主机地址

  • <mysql_port>:MySQL 端口(默认场景常见为 3306,现场以实际为准)

  • <mysql_user> / <mysql_pwd>:MySQL 用户与口令

  • <mysql_db>:MySQL database 名称

  • <mysql_table>:MySQL 表名

建议在执行前先确认三件事:MySQL 的主机/端口;MySQL 用户是否有权限;目标表是否存在且列结构与下方外表定义匹配。

提示:下面快速开始中的外表列 id/name 仅为示例(用于演示环境的简单表)。实际使用时,请按目标 MySQL 表的列顺序与类型调整外表列定义;不要假设所有目标表都是两列且列名/类型固定。

如何确认目标表列顺序/类型(用于定义外表列):

  • 在 MySQL 上执行:DESCRIBE <mysql_db>.<mysql_table>;

  • 或执行:SELECT ordinal_position, column_name, data_type FROM information_schema.columns WHERE table_schema='<mysql_db>' AND table_name='<mysql_table>' ORDER BY ordinal_position;

CREATE EXTENSION IF NOT EXISTS mysql_fdw;

DROP SERVER IF EXISTS mysql_svr CASCADE;
CREATE SERVER mysql_svr
FOREIGN DATA WRAPPER mysql_fdw
OPTIONS (
  host '<mysql_host>',
  port '<mysql_port>'
);

DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER mysql_svr;
CREATE USER MAPPING FOR CURRENT_USER
SERVER mysql_svr
OPTIONS (
  username '<mysql_user>',
  password '<mysql_pwd>'
);

DROP FOREIGN TABLE IF EXISTS ft_mysql_demo;
CREATE FOREIGN TABLE ft_mysql_demo (
  id   integer,
  name text
)
SERVER mysql_svr
OPTIONS (
  dbname '<mysql_db>',
  table_name '<mysql_table>'
);

SELECT * FROM ft_mysql_demo;

要点:

  • host/port 是 SERVER 级别选项;dbname/table_name 是 FOREIGN TABLE 级别选项(不要写到 CREATE SERVER 里)。

  • 外表列需与 MySQL 侧列类型兼容;首次验证建议先选简单表或只映射少量列。

3 常见用法

3.1 省略 dbname/table_name 的默认规则

如果 FOREIGN TABLE 未显式指定:

  • table_name 默认使用外表名

  • dbname 默认使用外表所在的 UDB schema 名

因此,常见用法是:在 UDB 中先创建一个与 MySQL database 同名的 schema,再在该 schema 下创建外表并省略 dbname

3.2 映射 MySQL 表

CREATE FOREIGN TABLE ft_t1 (
  id   integer,
  name text
)
SERVER mysql_svr
OPTIONS (dbname '<mysql_db>', table_name 't1');

3.3 映射 MySQL 查询

CREATE FOREIGN TABLE ft_q1 (
  id   integer,
  name text
)
SERVER mysql_svr
OPTIONS (dbname '<mysql_db>', sql_query 'SELECT id, name FROM t1 WHERE id <= 100');

4 写入能力与限制(先读这一段再做 UPDATE/DELETE)[复杂]

mysql_fdw 支持 INSERT/UPDATE/DELETE,但有一个关键限制:

  • 用于定位行的“唯一键”必须可用。mysql_fdw 需要依赖远端表的唯一性来生成 UPDATE/DELETE 的定位条件。

  • 实现限制:远端表的第 1 列必须是唯一的(通常就是主键列)。如果第 1 列不唯一,进行 INSERT/UPDATE/DELETE 会报错。

建议:

  • 需要写入时,把外表的第 1 列定义为 MySQL 表的主键列(或至少唯一键列),并保持列顺序一致。

  • 只做查询验证时,可以忽略本节。

5 诊断与运维

5.1 查看 mysql_fdw 版本

SELECT mysql_fdw_version();

5.2 查看/刷新下推列表(如启用 pushdown 配置)

SELECT * FROM mysql_fdw_display_pushdown_list();
SELECT * FROM mysql_fdw_display_pushdown_list(true);

6 连接失败排查(仅当报错时看)[复杂]

6.1 典型问题:找不到 libmysqlclient 或依赖缺失

如果报错指向 libmysqlclient.so* 或出现 not found,优先按下面步骤检查“库是否在包内、依赖是否齐全、是否对服务进程可见”。

假设交付包目录为 <安装包目录>(示例:/home/unvdb/work/UDB-TX-26)。

  1. 确认 mysql_fdw 与 libmysqlclient 是否存在:

ls -l <安装包目录>/lib/mysql_fdw.so
ls -l <安装包目录>/lib/libmysqlclient.so* 2>/dev/null
  1. 用 ldd 检查依赖是否缺失(出现 not found 就是“库缺失或路径未生效”):

ldd <安装包目录>/lib/mysql_fdw.so | egrep 'not found|libmysqlclient' || true
  1. 确认服务进程环境(以服务进程视角为准):

pgrep -af 'unvdbsvr'
PID=<服务进程PID>
tr '\0' '\n' < /proc/$PID/environ | egrep '^(LD_LIBRARY_PATH)='

说明:

  • 修改 <数据目录>/env.sh 后需要先关闭 UDB 服务进程,然后 source <数据目录>/env.sh 再启动,新的环境变量才会对服务进程生效。

6.2 典型问题:权限/认证失败

  • 确认 MySQL 账号能从 UDB 机器登录,且对 <mysql_db>.<mysql_table> 有权限。

  • MySQL 8 默认认证插件可能引发兼容性问题,建议优先使用简单用户名密码验证可连通性。