3DEXPERIENCE 数据库迁移实践:从Oracle到PostgreSQL的数据库结构对齐与数据落地

将企业级PLM平台3DEXPERIENCE的数据库从Oracle迁移到PostgreSQL,正在成为越来越多公司和组织的主动选择。开源带来的授权与成本弹性、更加开放可控的技术栈、对底层数据库更高程度的掌控,都是推动这一决策的现实理由。对3DEXPERIENCE平台而言,这是一条有价值并且走得通的路。
需要正视的是3DE与一般业务系统有一点不同:它与自身的数据库结构高度耦合,对表结构、字段类型、索引、约束等细节都比较敏感——一处非原生的约束、一个缺失的索引,都可能导致平台服务无法正常启动。正因如此,这类迁移真正的难点,往往不在如何把数据搬过去,而在动手之前就把范围界定清楚:哪些数据需要迁移、以何种方式迁移,以及如何在迁移完成后让平台保持它原本的结构状态。
本文是对一次真实迁移的复盘。迁移最终顺利完成:由Oracle平稳落入PostgreSQL,3DE的各应用程序接入转换后的数据库可以正常运行,业务对象访问无碍,用户侧无明显感知。过程中我们先后验证了两条路线——A 全量转换与 B 纯数据迁移,并系统处理了四类问题:数据库结构与类型差异、迁移辅助主键的清理、Oracle空字符串与PostgreSQL NULL的语义差异,以及数据迁移的性能与一致性。下文以Ora2Pg为例展开,相关结论对其他可实现等效语法转换的工具同样适用。需要说明的是,PostgreSQL数据库版本应以所用3DE版本官方认证支持的版本为准,总体流程,如图1。

图1 3DEXPERIENCE 数据库迁移总体流程
一、界定迁移范围:迁移究竟是哪一层
3DE的数据在架构上本就是分层的,这一点在产品设计之初便已确定:metadata存放在3DE平台的数据库中,图纸以及相关的设计文件由FCS承载,搜索能力则依托独立的索引数据(3DSpaceIndex)。理解了这一分层,迁移的范围也就清晰了——真正迁移有难度的,只有数据库中的metadata。
这一层具体指什么?正是在 3DE 中以业务对象形式呈现的那些定义:业务对象、对象之间的关系、策略与生命周期、属性、版本等结构化数据,落在数据库层面的`lxbo_xxxxxx`、`mx`等表中,这一层是本次迁移的全部难点所在,既要完成结构转换与字段类型对齐,又要处理约束和数据库索引。
另外两层则要轻得多。3DSpaceIndex服务于搜索,主要通过文件复制与配置接入完成,必要时可完全重建;FCS承载设计文件内容本身,同样以文件复制与路径、配置接入为主,并不触及数据库结构。
因此,真正需要投入工程资源严格管控的,只有metadata这一层。3DE数据分层与迁移边界,如图2。

图2 3DEXPERIENCE 数据分层与本次迁移边界
二、动手之前:备份、评估以及安装一套作为最终环境的原生库
正式迁移前,我们完成了三项铺垫工作。
第一,对原Oracle生产环境进行完整备份,数据库与应用配置一并纳入。迁移的根本风险,是失败之后无法回退,因此备份并非附属步骤,而是方案能否启动的前提。更稳妥的做法,是基于生产库建立一份克隆库,后续所有的数据抽取与临时改造(例如稍后需要为迁移工具添加的辅助主键)都在克隆库上进行,这样既不增加生产库的负载,也不会在其上留下残留对象。
第二,先进行一次迁移评估。在正式转换之前,借助Ora2Pg的SHOW_REPORT对源库进行盘点;如果需要进一步估算迁移工作量,也可以配合ESTIMATE_COST使用。评估内容包括数据库对象数量、数据量级、表结构复杂度、索引与约束情况,以及是否存在存储过程、触发器、物化视图等可能增加迁移复杂度的对象。对于3DE而言,核心业务逻辑主要集中在应用层,而不是依赖大量数据库存储过程。因此,本次评估的重点主要落在表结构、字段类型、约束、索引和数据量上。
第三,新建一套基于PostgreSQL的3DE环境。此举有两层用意。其一,获得由3DE官方安装程序创建的PostgreSQL原生数据库结构,作为后续结构对照与清理的基准。其二,也是更重要的一点,这套已经安装完成的3DE应用程序在迁移完成后将直接接入转换后的数据库,并对外提供服务。PostgreSQL 3DSpace安装,如图3。

图3 安装 PostgreSQL 版 3DE,以原生结构作为对照基准
三、A 路线:全量转换及其暴露的结构差异
3.1 路线与执行步骤
A路线是最直接的思路:让工具把结构与数据一并迁移过去。
Oracle数据库结构 → Ora2Pg 导出表结构 → 调整转换后的PostgreSQL DDL → 在PostgreSQL中创建表 → 导入数据 → 创建约束、索引、外键、视图和序列借助Ora2Pg 的项目化能力(`--init_project`会生成标准目录与导入脚本),导出按对象类型分阶段进行:先以`TABLE`导出结构,再以`COPY`或`INSERT`导入数据,随后依次处理`SEQUENCE`、`VIEW`、`GRANT`、`INDEXES`、`CONSTRAINT`。这里遵循一条比较通用的迁移原则:数据先行,索引、外键和部分约束后置。先完成表结构和数据导入,再创建索引、外键以及相关约束。这样既可以提高大批量数据加载速度,也便于在迁移过程中将数据问题和结构问题分开定位。A路线全过程,如图4。

图4 A 路线将结构与数据一并转换,用于完整暴露差异
3.2 暴露出的类型与命名差异
A路线的真正价值,在于它将Oracle经通用工具转换后、与3DE原生PostgreSQL数据库结构之间的差异完整呈现了出来。差异的根源在于:Ora2Pg遵循的是数据库通用转换规则,并不了解3DE在PostgreSQL原本的设计。当时主要整理出以下几类差异:
第一类是类型差异。
Oracle中大量字段为NUMBER(38,0)。Ora2Pg出于通用迁移的保守策略,通常会将其转换为numeric(38)。但在3DE原生PostgreSQL结构中,这些字段多数对应int4,部分对应int8,也有少量对应int2。字段最终应使用哪种整数类型,并不是单纯由Oracle字段精度决定,而是由3DE对该字段的业务语义决定。
Oracle中的RAW或RAW(16),在Ora2Pg默认转换中可能被处理为uuid,而3DE原生PostgreSQL结构中对应的是bytea;Oracle中的DATE也可能被转换为timestamp(0),而原生PostgreSQL结构中使用的是timestamp。
更重要的是,字段类型差异还会继续影响索引定义。例如字段如果被转换为numeric,相关索引可能使用numeric_ops;而在3DE原生PostgreSQL结构中,如果该字段实际是int8,对应索引则可能是int8_ops。因此,字段类型不是孤立问题,它会连带影响索引、约束以及数据库执行行为。同一字段的类型差异样例,如图5。

图5 同一字段在两套结构中的类型选择并不一致
第二类是主键、外键和约束命名差异。
Ora2Pg默认会忽略Oracle端的主键名,转而采用PostgreSQL内部的默认命名规则,只有显式开启`KEEP_PKEY_NAMES`才会保留Oracle名称。而3DE原生PostgreSQL结构使用的又是第三套——安装程序生成的名称。于是Oracle名、Ora2Pg生成的名字、3DE官方标准安装过程生成的原生命名三套并存,互相之间无法对应。不仅影响可比对性,也可能影响后续脚本、应用检查或迁移后结构对照。3.3 可由配置消除的部分差异
其中相当一部分差异,通过调整Ora2Pg配置即可消除。例如,原生PostgreSQL数据库使用的是timestamp类型,而Ora2Pg默认可能将其转换为timestamp(0)。对于这类具有明确、统一映射关系的类型差异,可以通过DATA_TYPE进行全局替换。该参数同样适用于RAW → bytea、DATE → timestamp等映射场景。timestamp与timestamp(0)的差异,如图6。

图6 timestamp 与 timestamp(0) 的差异对照
DATA_TYPE RAW:bytea,RAW(16):bytea,RAW(32):bytea,DATE:timestamp
此外,还可启用以下配置:
MODIFY_TYPE LXBO:bigint,LXOID:bigint,MXTOID:bigint,MXLATTICE:bigint,MXOID:bigint,MXSTARTTIME:bigint,
MXCOMMITTIME:bigint,LXFROMID:bigint,MXCOUNT:bigint # 用于覆盖对特定字段的默认类型转换结果,用于处理需要逐列指定的情形。
LOWER_CASE 1 # 标识符统一转小写,贴合 PG 习惯
KEEP_PKEY_NAMES 1 # 保留主键命名
KEEP_FKEY_NAMES 1 # 保留外键命名
DROP_INDEXES 1 # 索引与表结构分离、后置创建
IGNORE_TABLESPACE 1 # 忽略 Oracle的 tablespace 定义
3.4 真正无法自动解决的核心矛盾
参数能解决大半,但有一处始终无法逾越:同样是`NUMBER(38,0)`,究竟应转为`int2`、`int4`还是`int8`,工具自身无法判断。
`lxbo`、`mxoid`、`mxstarttime`这些列贯穿于几乎每一张对象表,属于内核的对象标识与时间戳字段。它们在原生PostgreSQL中取`int4`、`int8`还是`int2`,取决于3DE对该字段的业务定义,而非数据库精度可以推断。`PG_INTEGER_TYPE`按精度推断的结果,注定与3DE的实际选择对不齐。
而`MODIFY_TYPE`固然可以逐列固定,但其粒度是表X列,而`lxbo`、`mxoid`这类列横跨成百张表反复出现。若要以`MODIFY_TYPE`覆盖全库,需要枚举海量的表名:列名:类型组合并持续维护,虽可借助AI,但仍需耗费转换时间。
由此,A路线的定位也就清晰了:作为技术验证路线它极为有效,能将差异与风险一次性暴露完整;但若直接作为最终落地方案,参数调整与人工对齐的代价偏高。
四、B 路线:结构以原生为准工具只负责迁移数据
4.1 让工具回到数据迁移的本职
A路线将问题趟明后,思路随即收敛。B路线把工具的职责收回到数据搬运这一本职工作。
目标PostgreSQL数据库结构一律由3DE安装程序创建;Ora2Pg不再创建table、index、constraint、foreign key,它只负责将 Oracle的row data导入这套已经建好的原生数据库结构。
目标数据库结构既然不再经过工具生成,A路线中那一系列类型、命名、操作符类的差异就不复存在。考虑到3DE对自身数据库结构的敏感程度,它本就只认安装程序那一套。B路线过程,如图7。

图7 B 路线保留 3DE 原生 PostgreSQL 结构,仅迁移行数据
4.2 纯数据加载的落地要点
不过,B路线并非执行一遍COPY即告完成。向一套已建好的数据库结构灌入数据,有几处需要特别关照。
首先是目标表名必须正确映射。3DSpace 的部分数据表带有一段环境相关的后缀,例如 lxbo_xxx、lxstring_xxx、lxreal_xxx、lxdate_xxx 等。这段后缀不是随意命名,是在环境创建时生成的。也就是说,新安装一套 PostgreSQL 版 3DE 环境后,官方标准安装过程会生成属于该环境自己的表名后缀。因此,Oracle 源端与 PostgreSQL 目标端的部分表名天然不会完全一致。需要先建立表名映射关系:确认 Oracle 源端的 lx*_<源后缀> 应该对应 PostgreSQL 目标端的 lx*_<目标后缀>。在Ora2Pg中,可以通过类似 REPLACE_TABLES 的方式,在导入阶段完成表名替换。例如:
REPLACE_TABLES LXBO_xxx:lxbo_yyy LXSTRING_xxx:lxstring_yyy
不带分区后缀的 mx* 管理表,两端通常可以按同名导入。
其次是外键。目标库已带有外键约束,若不加约束地随意加载,必然触发冲突。可在加载期延迟或临时关闭外键(`FKEY_DEFERRABLE`/`DEFER_FKEY`),或先禁用触发器(`DISABLE_TABLE_TRIGGERS`),待数据导入完成后统一校验。其次是目标表的预清理——3DE官方安装程序建库时部分表自带初始化数据,导入前需按需`TRUNCATE`,以免与主键、唯一约束冲突或造成数据叠加。
序列同样容易被忽略。数据导入后,必须将各序列`setval`至Oracle端的当前最大值,否则新建对象会因ID重复而失败;Ora2Pg会生成相应的序列重置脚本,但需在数据导入之后执行方才有效。
性能方面,大表迁移可启用双端并行:Oracle端以`ORACLE_COPIES`并行抽取,PG端以`JOBS`并行写入,并辅以`DATA_LIMIT`控制批量大小;加载会话还可临时关闭`synchronous_commit`,对新建或清空的表启用`COPY FREEZE`,可观地压缩停机窗口。最后两处细节不可遗漏:其一是字符集,需确认源端`NLS_LANG`与目标库一致,避免中文与特殊符号在落库时损坏;其二是大对象,长文本与二进制字段须确认`CLOB→text`、`BLOB→bytea`映射正确,大字段的批量与超时单独评估。
4.3 迁移辅助主键:服务于工具不进入最终结构
B路线虽规避了大部分结构差异,但仍有一处细节须严格把关:辅助主键。3DE部分表在产品设计上本无主键,而某些迁移工具为保证数据唯一性与同步完整性,会要求源表具备主键。
合理的处理方式是:若需要主键,在Oracle克隆库上临时添加,仅服务于迁移过程的去重与同步;但这些主键不得进入目标PostgreSQL的最终结构。迁移完成后,将迁移后的数据库结构与一份干净安装的3DE数据库结构做比对,清除一切非原生的主键、唯一约束、外键与索引。如前所述,3DE启动时对数据库结构要求严格,残留的额外约束可能直接导致服务无法启动。
五、共同的问题:Oracle空字符串与PostgreSQL NULL
无论采用哪条路线,都会遇到二者的语义差异:Oracle将空字符串''视为NULL,而PostgreSQL中''是有效字符串,NULL为缺失值,二者界限分明,在3DE中会进一步影响业务语义。
最典型的是`revision`字段。某个对象的版本在业务语义上应为空字符串,但在Oracle中实际存储为NULL,迁移至PostgreSQL后若保持NULL,便可能影响对象的身份判断与检索。
修复少量对象可通过mql:
mod bus xxx name type_xxx revision "";
大批量数据:数据库层定向更新,效率高,但绕过3DE应用逻辑
UPDATE lxbo_xxx SET LXREV = '' WHERE LXREV IS NULL;
这里有一条不可逾越的原则:切勿全库无差别地将`NULL`替换为空字符串。 并非所有`NULL`都源自Oracle的空字符串,也并非所有字段在3DE业务语义中都应为空字符串。稳妥的做法是在随后的测试过程中建立字段级的修复清单,仅对业务语义明确要求空字符串的字段定向修复;对`revision`等关键字段,需在修复前后进行数据统计与业务核对。归根结底,这一问题的判断依据始终是3DE的业务语义,而非数据库层面的值是否为空——这也正是它无法被任何通用工具自动解决的原因。
六、迁移验证:SQL 执行成功,远不等于迁移完成
脚本全部执行成功,容易让人误以为迁移已经完成。但对3DE而言,真正的完成标准是三句话:数据库层数据完整、应用层业务可用、用户侧无明显感知。验证须分两层进行。迁移验收三层标准,如图8。

图8 迁移验收从 SQL 成功走向业务可用与用户无感
数据库层:逐表对比Oracle与PostgreSQL的`row count`;抽查关键数据库结构的表的数据与字段值;核对序列是否已`setval`对齐 Oracle的最大值;将迁移后的数据库结构 与3DE官方安装的数据库结构 比对,清理非原生的主键、唯一约束、外键与索引;核查`NULL`与空字符串的修复结果;确认字符集未导致多字节字段损坏;校验外键引用完整性。这部分内容可借助AI辅助完成,提高排查效率。
此外还有一项常被忽略——加载完成后执行一次`VACUUM ANALYZE`,刷新统计信息,避免迁移后查询因计划器统计陈旧而性能劣化。我们建议在迁移后使用dsDBUtils做一次数据库的维护。
业务层:站在用户视角完整走查一遍——3DE 服务是否正常启动、应用程序能否连接转换后的PostgreSQL、用户能否登录、业务对象能否查询/打开/修改/新建、`revision`/`name`/`type`等字段的业务语义是否正确、搜索功能是否正常、FCS文件能否正常访问、权限与生命周期流程是否正常。
最终的验收标准,不是某个组件单独可用,而是数据库、搜索、文件访问与业务功能共同恢复至可用状态,用户无从察觉底层数据库已经更换。
七、可复用的迁移经验
回顾整个项目,真正可以沉淀复用的,不是某一条命令或某一个参数,而是几个一经厘清便长期适用的判断。
迁移的核心和难点是数据库结构,而非FCS和3DSpaceIndex。所有数据抽取与临时改造均在克隆库上进行,生产库仅作为回退基线,保持不动。
最为关键的一条,是认清通用工具与产品原生设计之间的固有差距。Ora2Pg解决的是数据库通用转换,无法解决3DE的数据库结构对齐。因此正确的做法,是让官方安装程序创建结构、工具仅迁移数据(B路线),而非由工具重建结构再逐项修正(A路线)。B路线的价值在于降低人工成本和落地风险。与此相应,迁移过程中临时引入的对象就应保持其临时属性目标库最终必须回归官方安装程序的原生数据库结构。
其余两条偏重执行层面。空字符串与NULL须按业务语义定向处理,不可全库一刀切,底层批量修复后还需留意索引一致性;数据迁移要兼顾一致性与性能,延迟外键、关闭触发器、序列校准、迁移后使用dsDBUtils工具执行维护工作,缺一不可。验证应以业务功能可用和系统性能均达到迁移前水平为准,而非仅以SQL执行成功。
目前,达索已经提供官方数据库转换程序CopyMatrixDB,可用于转换3DSpace数据库。这是3DE平台中规模最大、结构最复杂的一部分业务数据,官方工具的出现显著降低了这部分数据库迁移的实施难度和结构风险。因此,对于CopyMatrixDB已经覆盖的3DSpace数据库,应优先采用官方工具完成转换,充分利用其原生适配能力。
但CopyMatrixDB尚未覆盖3DPassport、3DDashboard、3DSwym等其他平台组件的数据库,仍需借助通用工具完成迁移。对于这些数据库,仍应遵循本文验证后形成的原则。
归根结底,3DE由Oracle数据库迁移到PostgreSQL从来不是一次单纯的数据搬运,而是应用程序、数据库结构与平台对象模型重新对齐的一次项目工程。对公司和组织而言是一项收益明确的技术决策,而能否平稳落地,取决于执行时是否守住了那条边界:把通用转换交给工具,把数据结构与对象模型交还给产品本身。迁移真正的成果,不是数据库换了名字,而是平台在新的数据库底座上行为如常、用户毫无察觉。
童斌彬
钛闻软件
系统部主管
拥有10年以上Unix/Linux系统管理经验,长期从事Dassault Systemes 3DEXPERIENCE平台的架构设计、系统部署、性能优化及复杂问题处理。熟悉3DE平台整体架构、中间件和数据库运行机制,具备大规模用户、多站点及高可用环境的容量规划与实施经验。擅长从应用、系统和数据库多个层面定位问题,为企业客户提供架构咨询与技术支持。

关于钛闻软件

上海钛闻软件技术有限公司源自于上海江达科技发展有限公司,自2024年1月1日起,钛闻软件全面承接上海江达的人员、业务和相关资质。
钛闻软件在全国设有7个办事处,拥有超过200余人的专家顾问团队和近30年的行业经验,公司致力于向交通运输、工业装备、基础设施、航空航天、高科技电子及生命科学等行业客户提供先进的数字化解决方案及企业级应用系统。
作为达索系统重要的合作伙伴,钛闻软件在中国拥有1700多家客户。这些客户长期使用达索系统从需求、设计、工艺、仿真到制造的全生命周期解决方案,总装机量超过30000多套。钛闻软件非常注重客户的实施服务和应用支持,紧扣客户需求,引入最佳实践,让先进软件发挥卓越价值。
