
简介瀚高数据库抽取工具专为数据库管理员和运维开发人员设计解决Oracle数据库向瀚高HGDB数据库迁移及两库同步的问题。它内置数据抽取、转换和加载ETL流程能自动处理不同数据库间的数据类型和结构差异并针对Oracle的PL/SQL存储过程、触发器、索引等特性做了兼容优化需在JRE7环境下运行。压缩包共660个文件以dll、jar、properties、exe等类型为主包含可执行程序、Java依赖库以及大量时区和安全策略配置文件整体55.29MB。工具还提供直观的操作界面、数据加密和错误恢复机制迁移异常时可恢复至原状态降低数据丢失风险。目前已有775人学习适用于国产化替换、异构数据库迁移或主备库数据同步等场景。1. 瀚高数据库抽取工具Oracle 存量迁移先迈这一步手头还压着 Oracle 存量库的团队基本都绕不开这个场景目标库换成了瀚高数据库HGDB但数据还在老库的 Schema 里躺着业务系统只给了你两个礼拜窗口。导出脚本自己写一类字段一个坑用 Oracle 原生 expdp导出来的文件 HGDB 又不认。这个抽取工具解决的就是 Oracle 到 HGDB 的第一公里读 Oracle 数据字典拿结构按表逐批抽数据落成 HGDB 能直接装载的格式。它适合正在做信创选型、手上同时管着两套库的 DBA 和开发——工具不解决业务重构但能把结构迁移和数据落地这件事从“每张表手写一次”变成“配一次跑一批”。2. 抽取链路与核心能力结构、数据、装载三段各管什么2.1 工具定位它是离线抽取工具不是实时同步工具用之前先把边界划清楚。这个工具做的是离线分批抽取你跑一次它把 Oracle 侧的存量数据抽出来转成 HGDB 可识别的结构和数据文件。它不是 GoldenGate 那种日志解析实时同步也不接管增量。所以适合的场景是一次性存量迁移、测试库构建、数据仓库初装不适合的是生产双跑、实时灾备这类需要持续同步的业务。我一般会先用它做一次性全量再用业务侧或调度侧做增量补偿。原因很简单存量迁移最大的风险从来不是增量而是“抽到一半结构对不上”和“抽出来的数据目标库不兼容”。这个工具把结构和数据一并处理正好卡在迁移的痛点上。2.2 抽取流程拆解连接、解析、抽取、装载四段式工具的执行链路按四段走理解这个顺序能帮你快速定位问题出在哪一段阶段做什么常见失败特征连接同时建立 Oracle 与 HGDB 连接报 ORA-12170 / connection refused解析读 Oracle 数据字典生成建表语句与映射关系类型映射缺失日志里出现 skip抽取按表分批读取数据写入中间文件大字段断流、字符集乱码装载将中间文件写入 HGDB约束冲突、自增列丢失解析阶段是最容易出幺蛾子的地方。工具读的是 Oracle 的 ALL_TAB_COLUMNS、ALL_CONSTRAINTS 这些视图把字段类型翻译成 HGDB 的类型。这里翻译规则写得好不好直接决定后面数据装载顺不顺。比如 Oracle 的 NUMBER(1) 通常映射为 HGDB 的 SMALLINTNUMBER(10) 映射为 INTEGERNUMBER(18,4) 映射为 NUMERIC(18,4)。映射错了轻则精度丢重则整批装载失败。2.3 配置文件结构一个 Oracle 到 HGDB 的最小可用配置工具的所有行为都由一个配置文件驱动。我建议任何人在跑第一张表之前先把自己的配置精简到最小可用集验证链路通了再加复杂度。下面是一个能跑通的最小配置# 源库Oracle 侧连接与抽取行为 oracle.urljdbc:oracle:thin://192.168.10.20:1521/ORCLPDB oracle.usernamescott oracle.password从外部密钥文件读取 oracle.schemaSCOTT # 目标库HGDB 侧连接与装载行为 hgdb.urljdbc:postgresql://192.168.10.30:5432/hgdb hgdb.usernamehguser hgdb.password从外部密钥文件读取 hgdb.schemapublic # 抽取行为 extract.batchSize5000 extract.parallel4 extract.typeMappingFile./conf/type-mapping.properties load.createTabletrue load.convertUpperCaseToLowertrue逻辑上分三块源库连接、目标库连接、抽取与装载行为。值得先说穿的参数是load.convertUpperCaseToLower。默认 true 是因为 Oracle 侧未加引号的表名会统一变成大写存入数据字典而 HGDBPostgreSQL 系默认把未加引号的对象名折叠成小写。开着这个开关工具在生成建表语句时会把SCOTT.EMP转成scott.emp避免目标库出现“表建好了但查询要加双引号”的尴尬。另一个容易忽略的是extract.batchSize。它控制的是 Oracle 侧每次 FETCH 的行数不是总行数。我一般从 5000 开始如果网络环境差或大字段多降到 1000如果纯数值型小表可以拉到 10000收益不线性但能明显减少往返次数。3. 上手配置与命令行实操从单表到全库的完整操作3.1 环境准备与连接测试动手之前先把环境备齐。工具本身是免安装的 ZIP 包解压后目录结构大概长这样bin/放启动脚本conf/放配置文件lib/放 JDBC 驱动logs/放运行日志。需要确认两件事一是解压目录下有 Oracle JDBC 驱动ojdbc8 或 ojdbc11二是 HGDB 侧能通过 JDBC 连接。连接测试我习惯先去命令行验证不直接跑工具。Oracle 侧可以用 sqlplus 快速确认HGDB 侧用 psql 确认。两边通了再动工具能把“网络不通”和“工具报错”两类问题隔离开。# Oracle 侧连通性确认 sqlplus scott/password//192.168.10.20:1521/ORCLPDB EOF SELECT COUNT(*) FROM user_tables; EOF # HGDB 侧连通性确认 psql host192.168.10.30 port5432 dbnamehgdb userhguser -c SELECT version();这一步花不了五分钟却能省掉后面排查时一半的“连不上”问题。常见做法是先跑通最小的连通再叠加工具层的配置定位会更准。工具日志里如果报Connection refused基本就是网络或监听问题跟工具本身无关。3.2 单表抽取命令与参数说明环境就绪后第一次运行强烈建议只抽一张小表。先建目录映射文件指定源表与目标表的对应关系# 目录映射文件一行一组Oracle表名 - HGDB表名 echo SCOTT.EMP - public.emp ./conf/table-mapping.txt # 执行单表抽取 ./bin/extract-tool.sh \ --config ./conf/application.properties \ --tables ./conf/table-mapping.txt \ --mode schema-data \ --log-level INFO--mode schema-data表示同时抽结构和数据这也是存量迁移最常用的模式。如果你只想先拿建表语句做评审可以改成--mode schema-only只想抽数据不建表用--mode>-- HGDB 侧验证结构 \d public.emp -- HGDB 侧验证数据量 SELECT COUNT(*) FROM public.emp; -- Oracle 侧对照 SELECT COUNT(*) FROM scott.emp;两张表数量对得上工具链路就算基本通了。首次跑通后这组命令值得存成脚本后面每次批量迁移前都要用。3.3 全库抽取排除规则与并行度单表通了全库就容易了。全库模式下不需要--tables文件工具会读取 Oracle 侧ALL_TABLES把指定 Schema 下所有表都纳入抽取。但全量抽取前有几类表要先排除临时表、归档表、日志表、以及视图视图不是表工具默认不处理。排除规则写在配置文件里用正则匹配表名# 排除规则 extract.excludeTables.*TMP_.*,.*_LOG_.*,.*_ARCH_.* extract.excludeTypesINDEX,CLUSTERextract.parallel是并行抽取的线程数这里值得展开说。它不是开得越大越好我踩过的实际场景是并行度超过 8 后Oracle 侧 PGA 压力陡增HGDB 侧锁冲突变多整体耗时反而上升。一般 4 到 6 是甜点区。如果单表数据特别大可以在表级别用splitModepartition按 Oracle 分区做并行不要全局开满。全库抽取建议按schema-data模式跑中间文件落在工具目录的data/下。跑完后先抽查三张特征表——最大表、字段最多表、含分区表——确认无异常再决定是否需要切增量方案。4. 数据类型映射与一致性校验精度、字符集、时间格式三个暗礁4.1 Oracle 到 HGDB 的字段类型映射表类型映射是整个工具里最该提前研究的部分。工具内置了一套默认映射实际迁移时你大概率要按自己的业务字段做微调。我把常用的映射关系整理成表对照着改配置文件的typeMappingFile即可Oracle 类型HGDB 目标类型风险点NUMBER(1)SMALLINT布尔语义字段可能被截断NUMBER(5)INTEGER超出 21 亿会溢出NUMBER(10)INTEGER同上NUMBER(18)BIGINT安全NUMBER(18,4)NUMERIC(18,4)精度保留取决于 scale 定义VARCHAR2(50)VARCHAR(50)字节 vs 字符语义差异CHAR(10)CHAR(10)尾部空格可能被保留DATETIMESTAMP(0)不带时分秒的 DATE 会被补 00:00:00TIMESTAMP(6)TIMESTAMP(6)精度以括号内数字为准CLOBTEXT无需长度限制BLOBBYTEA二进制装载方式不同NUMBER族的映射是最容易出问题的。Oracle 的NUMBER是变长精度定义一个NUMBER不带参数时理论上可以存 38 位有效数字。HGDB 侧如果映射成NUMERIC还好映射成INTEGER就等着溢出报错。我的处理原则是见到不带精度的NUMBER一律按NUMERIC处理别省。4.2 精度与字符集三个容易翻车的具体场景第一个翻车点是字符语义。VARCHAR2(50)在 Oracle 里默认是字节语义受NLS_LENGTH_SEMANTICS影响50 个字节存不了 50 个汉字。工具映射成VARCHAR(50)后HGDB 侧按字符语义计算能放 50 个汉字。看起来容量变大了但如果源库本来就是按字节上限塞满的迁移后字符数量可能对不上。保险做法是源库侧先查字段的最大字节长度再按 4 倍字节数折算字符长度。第二个翻车点是DATE类型。Oracle 的DATE是日期加时间精确到秒。HGDB 侧映射成TIMESTAMP(0)没问题但如果源库某些字段只用日期不用时间装完后会出现2025-06-30 00:00:00业务侧比较日期时若用 2025-06-30会因时间部分不为空而查不到。我在做某跨平台系统迁移时就撞上过业务查了近一周的账明细对不上排查下来全是这类隐式条件。解决方法是映射文件里单独指定日期字段统一加一层格式化把时间归零。第三个翻车点是CHAR尾部空格。Oracle 的CHAR定长不足长度补空格HGDB 的CHAR同样是定长但装载工具在写入时可能不会帮你处理右填充。结果就是原来WHERE name ABC能命中迁移后name长度是 10字符串比较失败。处理方式是在装载阶段对CHAR字段执行RTRIM生成临时列再装入目标表。4.3 抽取后的数据校验手段数据装载完成后没人敢说“肯定没问题”。我通常用 SQL 对账代替抽样检查全部走自动化不做人工抽看。-- 表级校验结构一致性比对 SELECT table_name, column_name, data_type, character_maximum_length FROM information_schema.columns WHERE table_schema public ORDER BY table_name, ordinal_position; -- 行级校验抽出最大、最小、平均行长与 Oracle 侧比对 SELECT COUNT(*) AS row_cnt, MIN(LENGTH(row_data)) AS min_len, MAX(LENGTH(row_data)) AS max_len FROM public.emp;-- 哈希校验对整表做行序无关的聚合哈希 SELECT COUNT(*) AS row_cnt, SUM(hashtext(row_data::text)) AS total_hash FROM public.emp;做法是先在 Oracle 侧执行同一组聚合再把两条 SQL 的结果贴一起比对。行数、长度分布、聚合哈希三者一致基本可以确认数据层面没丢没串。哈希校验对“行数对得上但内容错位”的情况特别管用——两张表行数相同但某一行数据错位了COUNT(*)看不出来聚合哈希必挂。5. 避坑与排查手册表名乱码、大字段断流、自增列丢失的处理记录5.1 表名乱码与大小写问题现象抽取完成后HGDB 里多了一张名为EMP的表查询时SELECT * FROM EMP报“关系不存在”必须加双引号才能查。原因Oracle 侧不加引号的表名在数据字典里恒为大写工具生成建表语句时原样带了双引号HGDB 按双引号内原字面量建表于是表名变成了大写。解决开启配置里的大小写折叠开关让工具在生成 DDL 时统一降为小写已经跑出来的手动改表名回小写或重建。从那以后我每次新建抽取任务都把convertUpperCaseToLower放第一位检查。5.2 大字段抽取到一半连接断开现象某张含 CLOB/BLOB 的表抽取进度到 70% 左右报连接中断日志里出现ORA-03113或Communication channel failure。原因Oracle 服务端空闲连接超时SQLNET.EXPIRE_TIME未配或过短大批量抽取耗时较长连接在抽取间隙被服务端判定为死连接并断开。解决抽取前先确认 Oracle 侧的 idle timeout 配置临时把它调大或者让工具在抽取大字段表时加大 fetch size减少空闲间隙。如果网络层面有防火墙同步检查半小时无活动会话断开机制。记住一点大字段表的抽取时长不是按行数估的是按总字节数估的超长任务务必预先拉长各类超时。5.3 自增列到了 HGDB 变成普通列现象源表主键在 Oracle 里是IDENTITY或由序列触发自增装载到 HGDB 后发现没有默认值或序列插入数据必须手写主键。原因load.createTabletrue时工具默认执行的是建表语句但序列对象的创建脚本在schema-mode下不总是被生成尤其当源列是用触发器实现自增时工具没有解析触发器逻辑。解决映射文件里手动指定主键列并在映射规则中标注autoIncrementtrue工具会自动为 HGDB 侧生成GENERATED BY DEFAULT AS IDENTITY或配套序列。已经造成的表不用重抽直接在 HGDB 侧补上序列并设置默认值即可。5.4 空表在抽取后被跳过现象Oracle 侧一张有结构无数据的表抽取完成后在 HGDB 里找不到这张表。原因工具在schema-data模式下按“先抽数再建表”的顺序执行时空表被判断为“无数据需要装载”部分流程会把无数据表的建表语句一并跳过。解决把配置里的load.createTable与抽取逻辑解耦增加extract.forceCreateEmptyTablestrue参数强制空表也生成建表语句。这个参数在业务需要保持表结构完整性的场景如迁移后仍有定时插入任务是必须开的。5.5 时间字段装载后偏移 8 小时现象HGDB 侧查询数据发现所有TIMESTAMP字段都多了或少了 8 小时。原因Oracle 会话时区与 HGDB 侧时区不一致。Oracle 的TIMESTAMP WITH TIME ZONE在抽取时保留原时区值HGDB 端按服务端时区解析后做了转换直观表现就是整体偏移。解决在 Oracle 连接 URL 上强制指定会话时区并在 HGDB 侧统一时间字段语义。具体做法是在配置文件的 JDBC 连接串上加oracle.sessionTimeZoneAsia/Shanghai。映射文件里也可以手动指定字段按TIMESTAMP WITHOUT TIME ZONE装载避免隐式转换。这个坑很隐蔽单看数据值看不出问题必须用业务侧实际查询结果验证。6. 断点续传与并行抽取大数据量迁移前先试这两个技巧单表超过千万行时一次跑完容易失败重来。工具支持断点续传核心机制是每张表按主键或 RowNum 切成分片每个分片落一个中间文件同时更新进度记录。失败后重新运行工具会跳过data/下已存在的分片文件只补未抽完的片。配置很简单extract.resume.enabledtrue extract.splitModerownum extract.splitSize500000splitModerownum适合没有可靠主键的宽表按行号切片如果源表主键分布均匀可以用splitModeprimaryKey更稳。每个分片 50 万行抽出来是一个独立文件装载时 HGDB 侧逐文件COPY失败重跑只会从断点继续不会重复装载。并行抽取方面建议按表类型分两个队列小表按默认并行度抽大表单独串行抽。原因很实际——并行度开太高时Oracle 侧排序和临时表空间压力大一旦触发临时表空间不足所有并行任务一起失败。我在一个大宽表项目中吃过教训12 个线程同时抽一张 200 字段的业务表Oracle 侧临时表空间涨了 40G最后 ORA-01652 直接中断全批。后来改成单表串行、多表并行整体耗时只多了 15%但再没中断过。批量装载时我习惯先关掉 HGDB 侧的目标表索引和约束装完再统一重建。这个顺序能省 30% 左右的装载时间尤其在被装载表有多个二级索引时效果更明显。装载完成后记得做一次全库ANALYZE否则优化器的统计信息还是空的查询计划会跑偏。从那以后我每次做 Oracle 到 HGDB 的迁移都强制先跑一条万行级小表验证链路再全量执行最后用聚合哈希比对收尾三步缺一不可。这套流程帮我守住过不少次迁移的质量线希望帮到你。本文还有配套的精品资源点击获取