1. 为什么要在 Linux 上折腾 Fastexport 这个老工具
数据仓库领域做久了,总会碰到一些绕不开的“老家伙”。Fastexport 就是其中之一。它是 Teradata 官方提供的一款并行数据导出工具,核心能力是把 Teradata 数据库里的大表以极高的吞吐量拉到本地文件系统或者管道里。虽然现在很多团队已经转向了更现代的 Spark 连接器或者 Kafka 管道,但在一些存量系统里,Fastexport 依然是数据抽取环节的主力。
我最近接手的一个数据迁移项目就遇到了这个需求:需要从一套运行了七八年的 Teradata 环境里,把几十张宽表全量导出成带分隔符的文本文件,然后再加载到新的分析平台。客户环境是 CentOS 7 系列的 Linux 服务器,没有图形界面,只能通过命令行操作。Fastexport 的版本锁定在 1.7,这个版本虽然不算新,但胜在稳定,而且和客户现有的 Teradata 客户端工具集兼容性最好。
这篇文章就是记录我完整走一遍安装流程的实操笔记。我会把每一步为什么这么做、参数背后的逻辑、以及我踩过的坑都写清楚。如果你也面临类似的老系统数据导出任务,或者单纯想了解一下 Teradata 生态里的经典工具,这篇内容应该能帮你省下不少查文档和试错的时间。
需要提前说明的是,Fastexport 的安装包通常随 Teradata Tools and Utilities(简称 TTU)一起分发,单独拎出来安装的场景不多。但有些客户环境只买了 Fastexport 的授权,或者运维团队为了精简服务器只允许装这一个组件,这时候就需要我们手动处理依赖和配置。下面的内容就是针对这种“最小化安装”场景展开的。
2. 安装前的环境摸底与依赖确认
2.1 确认系统架构和库版本
拿到安装包之前,第一件事是确认目标服务器的 CPU 架构和操作系统版本。Fastexport 1.7 的安装包通常分为 32 位和 64 位两个版本,虽然现在绝大多数生产环境都是 x86_64,但保不齐会遇到一些老旧的 Power 或者 Itanium 机器。我习惯用下面这几条命令快速摸清底细:
uname -m cat /etc/redhat-release ldd --versionuname -m输出x86_64就说明是 64 位系统,对应选择fexp__linux-x86_64之类的包名。/etc/redhat-release能看出是 RHEL 还是 CentOS,以及具体的大版本号。这里有个经验:Fastexport 1.7 在 RHEL 6 和 RHEL 7 上的依赖库版本差异比较大,尤其是libstdc++和libgcc的版本。如果服务器是 RHEL 6,可能需要额外升级这些基础库,否则安装完运行时会报GLIBCXX_3.4.15 not found之类的错误。
ldd --version用来查看 glibc 的版本。Fastexport 1.7 最低要求 glibc 2.12,如果低于这个版本,基本可以放弃治疗,只能考虑升级操作系统或者找更老的 Fastexport 版本。我遇到过一台 CentOS 6.5 的机器,glibc 是 2.12,刚好卡在及格线上,安装过程倒是顺利,但运行时报了一堆符号找不到的问题,最后还是升级了系统才解决。
2.2 检查磁盘空间和临时目录
Fastexport 的安装包本身不大,解压后大概几百兆,但安装过程中会在/tmp目录下解压一些临时文件。如果/tmp分区太小(比如默认的 50MB),安装脚本会直接失败,而且报错信息往往很隐晦,只提示“无法写入临时文件”。我一般会提前检查一下:
df -h /tmp df -h /opt/opt是 Teradata 工具默认的安装目录,确保它有至少 2GB 的可用空间。如果/tmp空间不足,可以通过设置TMPDIR环境变量来指定其他目录,比如:
export TMPDIR=/home/teradata/tmp mkdir -p $TMPDIR这个细节很容易被忽略,但一旦踩坑,排查起来很费时间。因为安装脚本不会明确告诉你“/tmp 空间不够”,而是抛出一个模棱两可的错误码。
2.3 确认 Teradata 客户端库的兼容性
Fastexport 不是孤立运行的,它依赖 Teradata 的 CLI(Call Level Interface)库来连接数据库。在安装 Fastexport 之前,需要确认服务器上是否已经安装了兼容版本的tdicu、cliv2等基础包。可以用rpm -qa | grep -i teradata来查看:
rpm -qa | grep -i teradata如果输出为空,说明这是一台“干净”的机器,需要先安装 TTU 的基础组件。如果已经有了一些 Teradata 的包,就要注意版本匹配问题。Fastexport 1.7 通常要求cliv2的版本在 15.10 以上,tdicu的版本在 15.10 以上。版本不匹配的话,Fastexport 可能能装上,但连接数据库时会报“无法加载 CLI 库”的错误。
我个人的建议是:如果服务器上已经有一套完整的 TTU 环境,最好直接用 TTU 的安装介质来装 Fastexport,这样依赖关系会自动处理。只有在“最小化安装”的场景下,才需要手动逐个解决依赖。
3. 获取安装介质与校验完整性
3.1 从官方渠道获取正确的包
Teradata 的安装介质通常通过其官方支持门户下载,需要有效的账号和授权。下载页面里会列出很多组件,我们要找的是名字类似TTU_17.00.00.01_Linux_INDEP.zip或者单独列出的Fastexport包。这里有个坑:不同版本的 TTU 包里包含的 Fastexport 版本可能不一样。比如 TTU 16.20 里带的是 Fastexport 16.20,而我们要的是 1.7 版本,这个版本号其实是 Fastexport 自己的版本体系,和 TTU 的版本号不是一一对应的。
我下载到的包名是fexp__linux-x86_64.1.7.0.0-1.x86_64.rpm,这是一个标准的 RPM 包。如果你拿到的是.tar.gz格式的压缩包,里面通常包含一个install.sh脚本和一堆.rpm文件,安装方式会略有不同。
3.2 校验包的完整性
下载完成后,第一件事是校验 MD5 或 SHA256 值。官方下载页面通常会提供校验码,如果没有,至少也要确认文件大小和预期一致。我吃过一次亏:下载过程中网络中断,文件不完整,但安装脚本居然没报错,只是装完之后 Fastexport 命令找不到,排查了半天才发现是包本身有问题。
md5sum fexp__linux-x86_64.1.7.0.0-1.x86_64.rpm把输出和官方提供的 MD5 值对比一下,确认一致再继续。如果官方没提供,可以尝试解压 RPM 包看看内部结构是否完整:
rpm -qpl fexp__linux-x86_64.1.7.0.0-1.x86_64.rpm | head -20这条命令会列出 RPM 包里包含的文件列表,如果能看到/opt/teradata/client/.../bin/fexp之类的路径,说明包的结构是正常的。
4. 逐步安装 Fastexport 1.7 的完整过程
4.1 使用 RPM 命令安装主包
确认包没问题后,就可以开始安装了。我习惯用rpm -ivh而不是yum install,因为yum会自动解决依赖,但有时候会从非官方源拉取不兼容的包,反而把环境搞乱。手动安装虽然麻烦一点,但每一步都可控。
sudo rpm -ivh fexp__linux-x86_64.1.7.0.0-1.x86_64.rpm如果系统提示缺少依赖,比如libstdc++.so.6或者libaio,需要先手动安装这些依赖。在 CentOS 7 上,可以用:
sudo yum install -y libstdc++ libaio安装完成后,Fastexport 的可执行文件通常位于/opt/teradata/client/17.00/bin/fexp或者/usr/bin/fexp。可以用which fexp来确认:
which fexp如果输出为空,说明安装路径没有加入PATH环境变量,需要手动添加:
export PATH=$PATH:/opt/teradata/client/17.00/bin这个export只对当前会话有效,要永久生效需要写入/etc/profile.d/下的脚本文件。
4.2 处理常见的依赖缺失问题
安装过程中最常见的报错是缺少libstdc++.so.6(GLIBCXX_3.4.15)。这是因为 Fastexport 1.7 是用较新的 GCC 编译的,而老系统自带的libstdc++版本太旧。解决办法有两种:一是升级系统的libstdc++,二是从其他机器拷贝一个较新的libstdc++.so.6.0.20放到/usr/lib64/下并重建软链接。
我一般倾向于第一种方案,因为升级系统库更规范,不容易引发其他软件的兼容性问题。在 CentOS 7 上,可以这样操作:
sudo yum update -y libstdc++如果系统源里没有更新的版本,可以考虑从 CentOS 8 或者较新的 Fedora 源里单独下载libstdc++的 RPM 包,然后用rpm -Uvh强制升级。但这样做有风险,可能会影响其他依赖旧版本libstdc++的程序。所以更稳妥的做法是:只把新的libstdc++.so.6.0.20文件放到一个独立目录,然后通过LD_LIBRARY_PATH环境变量让 Fastexport 优先加载这个新库。
mkdir -p /opt/teradata/lib_override cp libstdc++.so.6.0.20 /opt/teradata/lib_override/ ln -s /opt/teradata/lib_override/libstdc++.so.6.0.20 /opt/teradata/lib_override/libstdc++.so.6 export LD_LIBRARY_PATH=/opt/teradata/lib_override:$LD_LIBRARY_PATH这种“库覆盖”的方式比较干净,不会污染系统全局环境,适合在客户的生产服务器上操作。
4.3 配置环境变量和路径
Fastexport 运行需要几个关键的环境变量。除了前面提到的PATH和LD_LIBRARY_PATH,还需要设置NLSPATH来指定消息文件的位置,否则 Fastexport 报错时只会显示错误码,看不到具体的错误描述。
export NLSPATH=/opt/teradata/client/17.00/tbuild/msg/%N.cat export COPLIB=/opt/teradata/client/17.00/lib export COPERR=/opt/teradata/client/17.00/lib这些变量最好写入一个专门的配置文件,比如/etc/profile.d/teradata.sh,这样每次登录都会自动加载:
sudo tee /etc/profile.d/teradata.sh << 'EOF' export PATH=$PATH:/opt/teradata/client/17.00/bin export LD_LIBRARY_PATH=/opt/teradata/lib_override:/opt/teradata/client/17.00/lib:$LD_LIBRARY_PATH export NLSPATH=/opt/teradata/client/17.00/tbuild/msg/%N.cat export COPLIB=/opt/teradata/client/17.00/lib export COPERR=/opt/teradata/client/17.00/lib EOF写完记得source一下让配置生效:
source /etc/profile.d/teradata.sh4.4 验证安装是否成功
安装完成后,不要急着跑数据导出任务,先用一个简单的命令验证 Fastexport 是否能正常启动:
fexp -h如果能看到帮助信息,说明可执行文件和环境变量都没问题。接下来可以尝试连接数据库:
fexp -u dbc -p password -h teradata_host -f /tmp/test_export.txt -s "SELECT 1;"这条命令会连接数据库,执行一个最简单的查询,然后把结果写到/tmp/test_export.txt。如果连接失败,通常会报“无法加载 CLI 库”或者“连接超时”。前者说明cliv2的路径没配好,后者可能是网络或者数据库端的问题。
我遇到过一种情况:fexp -h能正常显示帮助,但连接数据库时报CLI error 2: Unable to load library。排查后发现是LD_LIBRARY_PATH里缺少了cliv2的路径。Fastexport 依赖libcliv2.so,这个文件通常在/opt/teradata/client/17.00/lib/下,需要确保这个目录在LD_LIBRARY_PATH里。
5. 跑通第一个导出任务:从参数到结果
5.1 理解 Fastexport 的核心参数
Fastexport 的参数很多,但常用的就那么几个。我整理了一个表格,方便快速查阅:
| 参数 | 含义 | 是否必填 |
|---|---|---|
-u | 数据库用户名 | 是 |
-p | 数据库密码 | 是 |
-h | 数据库主机名或 IP | 是 |
-f | 输出文件路径 | 是 |
-s | 要执行的 SQL 查询 | 是 |
-F | 字段分隔符,默认是竖线 | 否 |
-R | 记录分隔符,默认是换行 | 否 |
-T | 并行度,指定多少个会话同时导出 | 否 |
-c | 字符集,比如 UTF8 | 否 |
-m | 最大错误数,超过则终止 | 否 |
其中-T参数是 Fastexport 的核心优势所在。它允许你指定多个会话并行工作,每个会话负责导出表的一部分数据。比如-T 8就是开 8 个并行会话。但并行度不是越高越好,需要根据数据库的负载能力和网络带宽来调整。我一般从 4 开始试,如果数据库 CPU 和 I/O 都没到瓶颈,再逐步往上加。
5.2 一个完整的导出示例
假设我们要从sales_fact表里导出所有数据,字段用逗号分隔,字符集用 UTF8,并行度设为 4。命令如下:
fexp -u etl_user -p etl_pass -h 192.168.1.100 \ -f /data/export/sales_fact.csv \ -s "SELECT * FROM sales_fact;" \ -F "," -c UTF8 -T 4执行后,Fastexport 会先连接数据库,解析 SQL,然后启动 4 个并行会话。每个会话会从表中读取一部分数据,最后合并写入同一个文件。这里有个细节:Fastexport 默认会在输出文件里加上一些元数据头信息,比如列名和数据类型。如果不需要这些,可以加-H参数跳过。
导出完成后,可以用wc -l统计行数,和数据库里的COUNT(*)对比一下,确认数据完整性:
wc -l /data/export/sales_fact.csv如果行数不一致,可能是导出过程中有错误被忽略了。Fastexport 默认遇到错误会继续执行,但会在日志里记录。可以加-m 1让它在遇到第一个错误时就终止,方便排查问题。
5.3 处理导出过程中的常见报错
跑第一个任务时,最容易遇到的报错是权限问题。比如输出目录没有写权限,或者数据库用户没有 SELECT 权限。前者可以通过chmod解决,后者需要联系 DBA 授权。
另一个常见问题是字符集不匹配。如果数据库用的是 LATIN1,而导出时指定了 UTF8,可能会报“无法转换字符”的错误。这时候需要确认数据库的实际字符集,然后调整-c参数。可以用下面的 SQL 查询数据库的字符集:
SELECT CHAR_SET_NAME FROM DBC.DBCInfoV WHERE INFO_KEY = 'CHARACTER SET';如果查询结果是 LATIN1,导出时就别指定 UTF8,或者让 DBA 确认是否可以转换。
6. 安装和使用中的那些坑与经验
6.1 权限问题:不要用 root 跑 Fastexport
很多新手习惯用sudo或者直接以 root 身份运行 Fastexport,觉得这样权限大、不会出错。但实际上,Fastexport 官方建议用普通用户运行,因为 root 用户的环境变量和普通用户不一样,可能会导致库加载失败。而且导出的文件如果属于 root,后续其他用户处理起来也麻烦。
我一般会创建一个专门的etl用户来跑导出任务:
sudo useradd -m -s /bin/bash etl sudo su - etl然后在etl用户的环境里配置好PATH和LD_LIBRARY_PATH。这样既安全,又避免了权限混乱。
6.2 并行度不是越高越好
前面提到-T参数控制并行度,但很多人会盲目设得很高,比如-T 32,觉得这样导出最快。实际上,并行度受限于数据库的 AMP 数量和网络带宽。如果并行度超过了 AMP 数量,多出来的会话会空闲等待,反而增加了协调开销。
一个经验公式是:并行度 = min(AMP 数量, 可用网络带宽 / 单会话带宽需求)。比如数据库有 16 个 AMP,网络带宽 1Gbps,单会话大概需要 50Mbps,那么并行度设为 16 左右比较合适。但实际中还要考虑数据库的并发负载,如果白天业务繁忙,最好把并行度降到 4 以下,避免影响正常查询。
6.3 大表导出时的文件切分策略
Fastexport 默认把所有数据写到一个文件里。如果表有几百 GB,单个文件会非常大,后续传输和处理都不方便。这时候可以用-f参数指定一个目录,Fastexport 会自动按会话切分文件,每个会话生成一个独立文件。
fexp -u etl_user -p etl_pass -h 192.168.1.100 \ -f /data/export/sales_fact_dir \ -s "SELECT * FROM sales_fact;" \ -T 8这样会生成 8 个文件,文件名类似sales_fact_dir.1、sales_fact_dir.2等。后续可以用cat合并,或者直接并行加载到目标系统。
6.4 监控导出进度和性能
Fastexport 运行时默认不显示进度,只能等它结束。如果导出时间很长,心里没底。可以加-v参数开启详细日志,或者用-l指定日志文件路径:
fexp -u etl_user -p etl_pass -h 192.168.1.100 \ -f /data/export/sales_fact.csv \ -s "SELECT * FROM sales_fact;" \ -T 4 -v -l /data/export/fexp.log日志里会记录每个会话的启动时间、处理行数、错误信息等。可以用tail -f实时查看:
tail -f /data/export/fexp.log如果发现某个会话长时间没有进展,可能是遇到了锁或者网络问题,需要进一步排查。
6.5 安装包版本与数据库版本的匹配
最后再强调一个容易被忽略的点:Fastexport 的版本要和数据库版本匹配。虽然 Fastexport 1.7 可以连接多个版本的 Teradata 数据库,但官方推荐使用和数据库同版本的 TTU 工具。比如数据库是 16.20,最好用 TTU 16.20 里带的 Fastexport。如果版本差距太大,可能会遇到协议不兼容的问题,表现为连接成功但查询报错。
我遇到过一台数据库是 15.10 的机器,装了 Fastexport 1.7(对应 TTU 17.00),结果查询时总是报“无效的会话参数”。后来换成 TTU 15.10 里的 Fastexport 就正常了。所以,如果条件允许,尽量保持版本一致。
7. 从安装到跑通,我总结的几条实用建议
整个流程走下来,最耗时的部分其实是环境准备和依赖处理。如果服务器是全新的,没有预装任何 Teradata 组件,那么从零开始装 Fastexport 大概需要 1 到 2 个小时,其中大部分时间花在解决库依赖和配置环境变量上。如果服务器上已经有完整的 TTU 环境,那么单独装 Fastexport 只需要几分钟。
我的建议是:如果只是临时用一下 Fastexport,可以考虑在一台已经装好 TTU 的机器上直接运行,避免在新机器上折腾依赖。如果必须在生产服务器上安装,一定要提前做好快照或者备份,因为升级libstdc++这类操作有可能会影响其他应用。
另外,Fastexport 的官方文档虽然详细,但很多细节藏在“Troubleshooting”章节里,而且不同版本的文档结构不一样。我习惯在安装前先把官方文档里的“Known Issues”和“Prerequisites”部分过一遍,把可能的问题提前规避掉。
最后分享一个小技巧:如果安装过程中遇到莫名其妙的错误,可以试试用strace跟踪一下 Fastexport 的系统调用,看看它到底在找哪个文件、加载哪个库。比如:
strace -f -e openat fexp -h 2>&1 | grep -i "no such file"这样能快速定位到缺失的库文件或者配置文件,比盲目猜测高效得多。