PostgreSQL 迁移同步到 PolarDB Oracle
创建 PostgreSQL 到 PolarDB Oracle 复制任务时,控制台提供结构复制、全量复制和增量复制选项。本文按当前页面中的结构复制加全量复制流程说明。
前提条件
已将 PostgreSQL 源数据源和 PolarDB Oracle 目标数据源添加至 NineData,且目标数据源状态为可用。如何添加,请参见添加数据源。
在创建复制任务时,目标数据源类型选择 PolarDB(兼容Oracle)。
复制任务需要访问源数据源和目标数据源。具体账号权限以创建任务时的预检查结果为准。
使用限制
- 当前链路的全量复制选项右侧显示周期性全量复制开关;是否启用以及后续参数以当前页面显示为准。
操作步骤
登录 NineData 控制台。
在左侧导航栏单击数据复制 > 数据复制。
在数据复制页面,单击右上角的创建复制。
在数据源与目标页签,按照下表进行配置,并单击下一步。
参数 说明 任务名称 输入数据同步任务的名称,为了方便后续查找和管理,请尽量使用有意义的名称。最多支持 64 个字符。 源数据源 同步对象所在的数据源。 目标数据源 接收同步对象的数据源。 目标数据库 选择将数据同步到目标的哪个数据库。 目标对象命名规则 选择对象名称从源端迁移到目标端后的大小写转换规则。 - 全部转小写:无论源端的命名规则如何,目标端的命名规则全部为小写。
- 保持与源一致:沿用源端的命名规则。
- 全部转大写:无论源端的命名规则如何,目标端的命名规则全部为大写。
复制类型 选择复制类型。 - 结构复制:只同步源数据源的库表结构,不同步数据。
- 全量复制:同步源数据源的所有对象和数据,即全量数据复制。右侧的开关为周期性全量复制的开关,更多信息,请参见周期性全量复制。
- 增量复制:在全量同步完成后,基于源数据源的日志进行增量同步。
图标为增量操作类型配置,可以根据需求取消勾选某一些操作类型,取消勾选后,这些操作会在增量同步中被忽略。
增量开始时间 复制类型仅为增量复制时需要选择。 - 从启动时间开始:以当前复制任务开始时间为基准,进行增量复制。
- 自定义时间:选择增量复制开始的时间点,您可以根据您的业务所在地域按需选择时区。如果将时间点配置为当前复制任务开始前,则如果该时间段内有 DDL 操作,复制任务将失败。
复制规格 复制任务的规格,规格越大复制的速率越高,将鼠标悬浮于 图标上即可查看每个规格对应的速率和配置信息。如果先配置数据复制任务再购买资源,可以在此选择需要的规格;如果先购买资源再配置任务,系统会选中购买资源时指定的规格,且无法在任务配置中变更。
目标库同名对象处理策略(选中结构复制时需要选择) - 预检查报错并停止任务:预检查阶段检测到同名表时,停止任务。
- 跳过并继续任务:预检查阶段检测到同名表时,发送提示并继续任务。 结构复制时,忽略该同名表。如果您同时进行了数据复制,则数据会在同名表中追加,而不会覆盖原有数据。
- 删除对象并重建:预检查阶段检测到同名表时,发送提示并继续任务。结构复制时,删除目标库同名表,并基于源库重新复制表结构。如果您同时进行了数据复制,则数据会在表结构复制完成后写入。
目标表存量数据处理策略(选中全量复制时需要选择) - 预检查报错并停止任务:预检查阶段检测到目标表中存在数据时,停止任务。
- 忽略目标存量数据,追加写入:预检查阶段检测到目标表中存在数据时,忽略该部分数据,追加写入其他数据。
- 清空目标存量数据,重新写入:预检查阶段检测到目标表中存在数据时,删除该部分数据,重新写入。
目标表增量数据冲突处理策略(选中增量复制时需要选择) - 运行时报错:增量复制过程中遇到目标数据已存在则报错,等待人工介入处理。
- 不更新目标数据:增量复制过程中遇到目标数据已存在则不写入,并继续后续任务。
- 更新目标数据:增量复制过程中遇到目标数据已存在则覆盖写入目标数据。
在选择复制对象页签,配置下列参数,然后单击下一步。
参数 说明 复制对象 选择需要复制的内容,您可以选择全部实例复制源库所有内容,也可以选择自定义对象,在源对象列表中选中需要复制的内容,单击>添加到右侧目标对象列表。 如果您需要创建多条相同复制对象的复制链路,可以创建一个配置文件,在新建任务的时候导入即可。单击右上角的导入配置,再单击下载模板,将配置文件模版下载到本地,编辑完成后单击上传文件上传该配置文件即可实现批量导入。字段和示例请参见导入复制对象配置模板。配置文件说明:
参数 说明 示例 source_table_name需同步的源表名。填写源数据源中实际存在的表名。 example_tbl_nametarget_table_name接收同步对象的目标表名。 example_tbl_namesource_database_name需同步的对象所在的源库名。 test_dbtarget_database_name接收同步对象的目标库名。 test_db_bakcolumn_list需要同步的字段列表。 ["col1", "clo2", "col3"]extra_configuration额外配置的 JSON 字符串。 column_rules用于配置字段映射与取值规则,其中column_name为源列名,target_column_name为目标列名,target_column_type为目标列类型,column_value为字段值;filter_condition用于配置行级过滤条件。{"extra_config": {"column_rules": [...]}}提示以下 JSON 表示下载的 Excel 模板中的两行示例数据。实际上传时,请保留 Excel 模板的列名,并将
extra_configuration单元格填写为 JSON 字符串;以下代码块不是可直接上传的 JSON 文件。[
{
"source_table_name": "example_tbl_name",
"target_table_name": "example_tbl_name",
"source_database_name": "test_db",
"target_database_name": "test_db_bak",
"column_list": ["col1", "clo2", "col3"],
"extra_configuration": {
"extra_config": {
"column_rules": [
{
"column_name": "example_column_name",
"target_column_name": "example_target_column_name",
"target_column_type": "int",
"column_value": "current_timestamp()"
},
{
"column_name": "example_column_name",
"target_column_name": "example_target_column_name",
"target_column_type": "int"
}
],
"filter_condition": "example_condition_expression"
}
}
},
{
"source_table_name": "example_order_tbl",
"target_table_name": "example_order_tbl",
"source_database_name": "test_db",
"target_database_name": "test_db_bak",
"column_list": ["col1", "clo2", "col3"],
"extra_configuration": {
"extra_config": {
"column_rules": [
{
"column_name": "example_column_name",
"target_column_name": "example_target_column_name",
"target_column_type": "int",
"column_value": "current_timestamp()"
},
{
"column_name": "example_column_name",
"target_column_name": "example_target_column_name",
"target_column_type": "int"
}
],
"filter_condition": "example_condition_expression"
}
}
}
]在配置映射页签,根据所选的复制类型选择不同操作,然后单击保存并预检查。如果在配置映射阶段,源和目标数据源中有更新,可以单击页面右上角的刷新元数据按钮,重新获取源和目标数据源的信息。
包含结构复制:配置目标表同步到目标数据源之后的表名。
不包含结构复制:系统默认选择目标数据源中的同名数据库,如果不存在,则需要手动选择目标库。目标库中的表名、列名需要和同步对象一致。如果不一致,您也可以手动进行表名和列名的映射。
您还可以进行如下操作:
- 单击页面右侧的映射与过滤,自定义列名同步到目标数据源之后的名称。
- 在映射与过滤页面,在数据过滤条件下方的文本框中输入比较表达式作为过滤条件,仅符合过滤条件的数据会同步到目标数据源。例如,将过滤条件设置为
emp_no>=10005,则 emp_no 列中小于 10005 的数据均不会同步到目标数据源。 - 单击"目标表名"右侧的
图标,可搜索表名,并替换成目标名称。
- 在右上角的搜索表文本框中输入表名以快速定位到目标表。
- 单击右上角的批量配置,可以批量定义通用规则(如表名、字段名大小写转换、前后缀添加、替换等),实现对大量表和字段的统一映射配置。
- 单击 Object Owner 右侧的下拉菜单,可以指定对象的所有者。下拉菜单的可选项和默认值以当前页面显示为准。
- 单击页面中的设置 Tablespace,可为目标数据源中的表和索引分别指定所属的 Tablespace,用于控制对象在目标库中的物理存储位置;若不进行设置,则默认使用目标数据库用户的默认 Tablespace。
在预检查页签,等待系统完成预检查,预检查通过后,单击启动任务。
您可以勾选开启数据一致性对比。在同步任务完成后,自动开启基于源数据源的数据一致性对比,保证两端数据一致。根据您选择的复制类型,开启数据一致性对比的启动时机如下:
- 结构复制:结构复制完成后启动。
- 结构复制+全量复制:全量复制完成后启动。
- 全量复制:全量复制完成后启动。
- 结构复制+全量复制+增量复制、增量复制:当增量数据首次和源数据源一致且延迟为 0 秒时启动。您可以单击查看详情,在复制详情页面中查看同步延迟。

如果预检查未通过,需要单击目标检查项右侧操作列的详情,排查失败的原因,手动修复后单击重新检查重新执行预检查,直到通过。
检查结果为警告的检查项,可视具体情况修复或忽略。
在启动任务页面,提示启动成功,同步任务开始运行。此时您可以进行如下操作:
单击查看详情查看同步任务各个阶段的执行情况。
- 单击返回列表可以返回数据复制任务列表页面。
修改增量同步位点
对于复制类型中包含增量复制且任务详情提供位点管理的任务,可以查看并修改同步位点。可用的位点类型和输入格式由当前数据源及复制链路决定,以页面显示为准;如果位点显示为 - 或位点类型没有可选项,则当前任务没有可供修改的位点。
该功能用于特定运维场景:重新指定增量任务的日志读取位置或同步写入位置。读取位点控制任务从源端哪个位置继续读取,写入位点控制任务从哪个位置继续处理同步写入;提交后任务会暂停并重新启动,使新的位点生效。
在复制任务列表中,单击目标任务的任务 ID,进入任务详情。
单击增量复制页签,然后单击同步位点管理,查看当前的读取位点和写入位点。
单击修改位点。在位点类型中选择要调整的读取位点或写入位点,再根据页面显示的位点类型填写调整位点。
确认值和影响范围后,单击验证并提交。任务会进入暂停和重新启动过程;任务恢复运行后,再次打开同步位点管理确认位点已更新。
修改同步位点,将会调整日志读取或同步写入的点位,可能导致数据丢失,谨慎操作! 修改任一位点都可能导致数据丢失或源端与目标端数据不一致。请仅在已授权的测试环境,或已完成备份并具备回滚方案的维护窗口执行。已完成增量复制的任务不能重置位点。
数据类型映射
下表记录 NineData Test 中 PostgreSQL 15.7 到 PolarDB PostgreSQL 14.18.37.0(Oracle 兼容模式)的结构加全量复制结果。目标类型和目录属性来自复制后目标列的目录查询。当前已确认 107 个源类型声明及参数组合:44 个基础和参数类型、32 个特殊类型、12 个范围和多范围类型、10 个附加别名及无长度限定类型,以及 9 个系统目录类型。基础类型、10 个附加类型和 9 个系统目录类型批次的源表为空,仅确认列映射;特殊类型和范围类型批次各复制并读取了 1 行。
这 10 个附加类型和 9 个系统目录类型来自各自独立的空测试表。结果只确认目标列类型和目录属性,不确认 serial 列的序列/默认值行为,也不确认这些空表中的数据值转换。
上表仅对应列出的 PostgreSQL 15.7 源类型;下方数组表单独对应 PostgreSQL 15.2。未列出的内部类型、扩展类型和用户自定义类型不得据此推断;类型映射也不代表其他参数下的行为。
类型清单参考 PostgreSQL 15 数据类型、数组类型、范围类型、对象标识符类型和 pg_type 系统目录。
| PostgreSQL 源类型 | PolarDB Oracle 目标列类型 | 目标目录属性 |
|---|---|---|
smallint | smallint (int2) | precision 16,scale 0 |
int2 | smallint (int2) | precision 16,scale 0 |
integer | integer (int4) | precision 32,scale 0 |
int | integer (int4) | precision 32,scale 0 |
int4 | integer (int4) | precision 32,scale 0 |
bigint | bigint (int8) | precision 64,scale 0 |
int8 | bigint (int8) | precision 64,scale 0 |
bigserial | bigint (int8) | precision 64,scale 0 |
smallserial | smallint (int2) | precision 16,scale 0 |
serial | integer (int4) | precision 32,scale 0 |
numeric | numeric | 未报告精度和小数位 |
decimal | numeric | 未报告精度和小数位 |
numeric(12,4) | numeric | precision 12,scale 4 |
decimal(12,4) | numeric | precision 12,scale 4 |
real | real (float4) | precision 24 |
float4 | real (float4) | precision 24 |
float(24) | real (float4) | precision 24 |
double precision | double precision (float8) | precision 53 |
float | double precision (float8) | precision 53 |
float8 | double precision (float8) | precision 53 |
float(25) | double precision (float8) | precision 53 |
boolean | boolean (bool) | — |
bool | boolean (bool) | — |
character(3) | character (bpchar) | length 3 |
char(3) | character (bpchar) | length 3 |
character | character (bpchar) | length 1 |
character varying(20) | character varying (varchar) | length 20 |
varchar(20) | character varying (varchar) | length 20 |
character varying | text | 未报告最大长度 |
bpchar | text | 未报告最大长度 |
text | text | — |
bytea | bytea | — |
date | date | — |
time(3) without time zone | time without time zone (time) | datetime precision 3 |
time(3) with time zone | time with time zone (timetz) | datetime precision 3 |
timestamp(3) without time zone | timestamp without time zone (timestamp) | datetime precision 3 |
timestamp(3) with time zone | timestamp with time zone (timestamptz) | datetime precision 6 |
timestamptz(3) | timestamp with time zone (timestamptz) | datetime precision 6 |
interval(3) | interval | datetime precision 6 |
interval year to month | interval | datetime precision 6;目录未显示字段限定符 |
interval day to second(3) | interval | datetime precision 6;目录未显示字段限定符 |
bit(4) | bit | length 4 |
bit | bit | length 1 |
bit varying(8) | bit varying (varbit) | length 8 |
varbit(8) | bit varying (varbit) | length 8 |
bit varying | bit varying (varbit) | 未报告最大长度 |
uuid | uuid | — |
json | json | — |
jsonb | jsonb | — |
jsonpath | jsonpath | — |
xml | xml | — |
money | money | — |
point | point | — |
line | line | — |
lseg | lseg | — |
box | box | — |
path | path | — |
polygon | polygon | — |
circle | circle | — |
cidr | cidr | — |
inet | inet | — |
macaddr | macaddr | — |
macaddr8 | character varying (varchar) | length 255 |
name | name | — |
"char" | character (bpchar) | length 1 |
tsquery | tsquery | — |
tsvector | tsvector | — |
pg_lsn | pg_lsn | — |
pg_snapshot | pg_snapshot | — |
txid_snapshot | txid_snapshot | — |
oid | oid | — |
regclass | regclass | — |
regcollation | regcollation | — |
regconfig | regconfig | — |
regdictionary | regdictionary | — |
regnamespace | regnamespace | — |
regoper | regoper | — |
regoperator | regoperator | — |
regproc | regproc | — |
regprocedure | regprocedure | — |
regrole | regrole | — |
regtype | regtype | — |
xid | xid | — |
xid8 | xid8 | — |
tid | tid | — |
refcursor | refcursor | — |
int4range | int4range | — |
int8range | int8range | — |
numrange | numrange | — |
tsrange | tsrange | — |
tstzrange | tstzrange | — |
daterange | daterange | — |
int4multirange | int4multirange | — |
int8multirange | int8multirange | — |
nummultirange | nummultirange | — |
tsmultirange | tsmultirange | — |
tstzmultirange | tstzmultirange | — |
datemultirange | datemultirange | — |
aclitem | aclitem (aclitem) | 未报告长度或精度 |
cid | cid (cid) | 未报告长度或精度 |
gtsvector | gtsvector (gtsvector) | 未报告长度或精度 |
pg_brin_bloom_summary | pg_brin_bloom_summary (pg_brin_bloom_summary) | 未报告长度或精度 |
pg_brin_minmax_multi_summary | pg_brin_minmax_multi_summary (pg_brin_minmax_multi_summary) | 未报告长度或精度 |
pg_dependencies | pg_dependencies (pg_dependencies) | 未报告长度或精度 |
pg_mcv_list | pg_mcv_list (pg_mcv_list) | 未报告长度或精度 |
pg_ndistinct | pg_ndistinct (pg_ndistinct) | 未报告长度或精度 |
pg_node_tree | pg_node_tree (pg_node_tree) | 未报告长度或精度 |
PostgreSQL 15.2 内置数组类型
下表对应 PostgreSQL 15.2 到同一目标版本的复制结果。76 个源数组列均复制为目标目录类型 ARRAY,udt_name 按目标列目录查询记录。此批次复制的数组值均为 NULL,因此表格只确认列类型,不代表非空或空数组值的转换结果。interval[] 的结构复制曾需修正生成的目标 DDL 后完成。
| PostgreSQL 15.2 源数组类型 | PolarDB 目标列类型 | 目标目录 udt_name |
|---|---|---|
aclitem[] | ARRAY | _aclitem |
bigint[] | ARRAY | _int8 |
bit varying[] | ARRAY | _varbit |
bit[] | ARRAY | _bit |
boolean[] | ARRAY | _bool |
box[] | ARRAY | _box |
bytea[] | ARRAY | _bytea |
char[] | ARRAY | _bpchar |
character varying[] | ARRAY | _varchar |
character[] | ARRAY | _bpchar |
cid[] | ARRAY | _cid |
cidr[] | ARRAY | _cidr |
circle[] | ARRAY | _circle |
date[] | ARRAY | _date |
datemultirange[] | ARRAY | _datemultirange |
daterange[] | ARRAY | _daterange |
double precision[] | ARRAY | _float8 |
gtsvector[] | ARRAY | _gtsvector |
inet[] | ARRAY | _inet |
int2vector[] | ARRAY | _int2vector |
int4multirange[] | ARRAY | _int4multirange |
int4range[] | ARRAY | _int4range |
int8multirange[] | ARRAY | _int8multirange |
int8range[] | ARRAY | _int8range |
integer[] | ARRAY | _int4 |
interval[] | ARRAY | _interval |
json[] | ARRAY | _json |
jsonb[] | ARRAY | _jsonb |
jsonpath[] | ARRAY | _jsonpath |
line[] | ARRAY | _line |
lseg[] | ARRAY | _lseg |
macaddr[] | ARRAY | _macaddr |
macaddr8[] | ARRAY | _varchar |
money[] | ARRAY | _money |
name[] | ARRAY | _name |
numeric[] | ARRAY | _numeric |
nummultirange[] | ARRAY | _nummultirange |
numrange[] | ARRAY | _numrange |
oid[] | ARRAY | _oid |
oidvector[] | ARRAY | _oidvector |
path[] | ARRAY | _path |
pg_lsn[] | ARRAY | _pg_lsn |
pg_snapshot[] | ARRAY | _pg_snapshot |
point[] | ARRAY | _point |
polygon[] | ARRAY | _polygon |
real[] | ARRAY | _float4 |
refcursor[] | ARRAY | _refcursor |
regclass[] | ARRAY | _regclass |
regcollation[] | ARRAY | _regcollation |
regconfig[] | ARRAY | _regconfig |
regdictionary[] | ARRAY | _regdictionary |
regnamespace[] | ARRAY | _regnamespace |
regoper[] | ARRAY | _regoper |
regoperator[] | ARRAY | _regoperator |
regproc[] | ARRAY | _regproc |
regprocedure[] | ARRAY | _regprocedure |
regrole[] | ARRAY | _regrole |
regtype[] | ARRAY | _regtype |
smallint[] | ARRAY | _int2 |
text[] | ARRAY | _text |
tid[] | ARRAY | _tid |
time with time zone[] | ARRAY | _timetz |
time without time zone[] | ARRAY | _time |
timestamp with time zone[] | ARRAY | _timestamptz |
timestamp without time zone[] | ARRAY | _timestamp |
tsmultirange[] | ARRAY | _tsmultirange |
tsquery[] | ARRAY | _tsquery |
tsrange[] | ARRAY | _tsrange |
tstzmultirange[] | ARRAY | _tstzmultirange |
tstzrange[] | ARRAY | _tstzrange |
tsvector[] | ARRAY | _tsvector |
txid_snapshot[] | ARRAY | _txid_snapshot |
uuid[] | ARRAY | _uuid |
xid[] | ARRAY | _xid |
xid8[] | ARRAY | _xid8 |
xml[] | ARRAY | _xml |
附录:预检查项一览表
| 检查项 | 检查内容 |
|---|---|
| 源数据源连接检查 | 检查源数据源网关状态、实例是否可达、用户名及密码准确性。 |
| 目标数据源连接检查 | 检查目标数据源网关状态、实例是否可达、用户名及密码准确性。 |
| 源库权限检查 | 检查源数据库账号权限是否满足要求。 |
| 循环链路检查 | 检查是否存在循环链路。 |