十二月 28, 2023
摘要:ora_migrator
是一个用于db_migrator
的插件,它使用oracle_fdw
将 Oracle 数据库迁移到 PostgreSQL。
目录
介绍
ora_migrator
是一个用于db_migrator
的插件,它使用oracle_fdw
将 Oracle 数据库迁移到 PostgreSQL。
请阅读db_migrator
文档以获取使用说明;本文仅涵盖插件的设置以及一般文档中未涵盖的其他功能。
除此之外,ora_migrator
还提供从 Oracle 到 PostgreSQL 的复制功能,可用于从 Oracle 进行几乎零停机时间的迁移。有关详细信息,请参阅复制。
请注意,由于 Oracle 中的模式名称通常为大写,因此,您需要为db_migrator
函数的only_schemas
参数,使用大写的模式名称。
选项
以下选项可用于db_migrate_prepare
、db_migrate_mkforeign
和db_migrate
:
max_long
(整型,默认值 32767):将用于在外表上设置max_long
选项。这决定了 LONG、LONG RAW 和 XMLTYPE 列的最大长度。
前提条件
-
您需要 PostgreSQL 9.5 或更高版本。
-
必须安装
oracle_fdw
和db_migrator
扩展。 -
必须为访问的 Oracle 数据库定义好外部服务器。
-
调用
create_oraviews
函数以创建外部表的用户,必须具有外部服务器的USAGE
权限。 -
调用
create_oraviews
函数的用户必须存在用户映射。 -
用户映射中使用的 Oracle 用户,必须具有读取以下 Oracle 系统视图的权限:
DBA_COL_PRIVS
DBA_CONS_COLUMNS
DBA_CONSTRAINTS
DBA_IND_COLUMNS
DBA_IND_EXPRESSIONS
DBA_INDEXES
DBA_MVIEWS
DBA_MVIEW_LOGS
DBA_PROCEDURES
DBA_SEGMENTS
DBA_SEQUENCES
DBA_SOURCE
DBA_TAB_COLUMNS
DBA_TAB_PRIVS
DBA_TABLES
DBA_TRIGGERS
DBA_USERS
DBA_VIEWS
您可以选择改为授予用户
SELECT ANY DICTIONARY
系统权限,它包括了上述所有权限。 -
要使用复制,用户必须具有
CREATE TABLE
和CREATE TRIGGER
权限。若要对不属于指定 Oracle 用户的表使用复制,该用户必须具有
CREATE ANY TABLE
、CREATE ANY INDEX
、CREATE ANY TRIGGER
、DROP ANY TABLE
、DROP ANY TRIGGER
和SELECT ANY TABLE
权限(这是创建、删除日志记录表和触发器所必需的)。
扩展创建的对象
迁移函数
db_migrator
回调函数db_migrator_callback()
,返回扩展提供的迁移函数。有关详细信息,请参阅db_migrator
文档。
“元数据视图创建函数”create_oraviews
,会在 FDW 阶段创建一些附加对象,这些对象提供了对 Oracle 迁移有帮助的信息:
包定义
packages (
schema text NOT NULL,
package_name text NOT NULL,
is_body boolean NOT NULL,
source text NOT NULL
)
is_body
,对于包规范定义是FALSE
,对于包体定义是TRUE
此视图可用于简化包对象的转换。
段
segments (
schema text NOT NULL,
segment_name text NOT NULL,
segment_type text NOT NULL,
bytes bigint NOT NULL
)
该外表对于评估 Oracle 中表和索引的大小最有用。
迁移成本估算
migration_cost_estimate (
schema text NOT NULL,
task_type text NOT NULL,
task_content bigint NOT NULL,
task_unit text NOT NULL,
migration_hours integer NOT NULL
)
-
task_type
可以是tables
、data_migration
、functions
、triggers
、packages
和views
之一。 -
task_content
是该类型的任务数量 -
task_unit
是task_content
的单位 -
migration_hours
是对完成此任务可能需要的小时数的一个粗略估计
该视图有助于评估一个 Oracle 数据库的迁移成本。
其他对象
表函数 oracle_test_table
此函数测试一个 Oracle 表是否存在潜在的迁移问题。您必须在db_migrate_prepare
之后运行它。
参数为:
-
server
:Oracle 外部服务器的名称 -
schema
:模式名称 -
table_name
:表名 -
pgstage_schema
(默认是pgsql_stage
):由db_migrate_prepare
创建的 PostgreSQL 阶段的名称。
schema
和table_name
必须是 PostgreSQL 阶段中与tables
表同名的列中的值。
这是一个表函数,返回有问题的行在 Oracle 中的 ROWID,以及一条描述问题的消息。
目前测试发现有两个问题:
- 字符串列中的零字节
chr(0)
- 不在数据库编码中的字符串列中的值
函数 oracle_migrate_test_data
此函数对 PostgreSQL 暂存模式中的所有表调用oracle_test_table
,并将结果记录在 FDW 阶段的test_error
表中(在清空表后)。
此外,在 FDW 阶段,会有一份错误摘要添加到表test_error_stats
中。在清理 Oracle 中的脏数据时,这对于衡量随时间推移的进度非常有用。
该函数会返回遇到的错误总数。
函数参数为:
server
:Oracle 外部服务器的名称staging_schema
(默认是fdw_stage
):远程暂存模式的名称pgstage_schema
(默认是pgsql_stage
):由oracle_migrate_prepare
创建的 PostgreSQL 阶段的名称。only_schemas
(默认是NULL
):应迁移到 PostgreSQL 的 Oracle 模式名称数组。如果为 NULL,则会处理除 Oracle 系统模式之外的所有模式。名称必须与它们出现在 Oracle 中的名称相同,通常为大写。
表 oracle_test_table 和 test_error_stats
这些表包含运行oracle_migrate_test_data
生成的单个结果和汇总结果。
复制函数
函数 oracle_replication_start
此函数在 Oracle 和 PostgreSQL 数据库中创建复制所需的所有对象。PostgreSQL 对象将创建在 Postgres 暂存模式中,Oracle 对象与复制的表位于同一模式中。
此函数应在db_migrate_tables
之前调用,并且在启动oracle_replication_start
和调用db_migrate_tables
之间,不应在 Oracle 上发生任何数据修改活动。
函数参数为:
-
server
:Oracle 外部服务器的名称 -
pgstage_schema
(默认是pgsql_stage
):由oracle_migrate_prepare
创建的 PostgreSQL 阶段的名称
该函数创建的对象包括:
-
一个 PostgreSQL 外表
__ReplicationEnd
,该表会显示一个时间戳,保证能早于 Oracle 上最老的活跃事务 -
一个 PostgreSQL 表
__ReplicationStart
,用于存储下一次复制追赶的起点
对于 Postgres 阶段的tables
表中设置migrate
为TRUE
的每个表,将创建以下对象:
-
一个 Oracle 表
__Log_<tablename>
,用于收集对<tablename>
的更改 -
一个在
<tablename>
上面的 Oracle 触发器__Log_<tablename>_TRIG
-
Oracle 记录更改的日志表,在 PostgreSQL 上的外表
__Log_<schema>/<tablename>
函数 oracle_catchup_table
将特定时间间隔内更改的数据,从 Oracle 表复制到 PostgreSQL。
这要求oracle_replication_start
已创建所需的对象,并且数据迁移已完成。
参数:
-
schema
:迁移表的模式 -
table_name
:迁移表的名称 -
from_ts
:复制该时间点以后的更改 -
to_ts
:复制该时间点以前(包括该时间点)的更改
这是一个“底层”函数,由oracle_replication_catchup
调用;如果要通过为不同的表并发运行它,来并行化追赶任务,则可以使用它。
函数 oracle_catchup_sequence
参数:
-
schema
:迁移序列的模式 -
sequence_name
:迁移序列的名称 -
staging_schema
(默认是fdw_stage
):远程暂存模式的名称
在远程端查询 Oracle 序列的当前值,并将迁移的序列设置为该值。
函数 oracle_replication_catchup
复制自上次同步到 PostgreSQL 以后所有 Oracle 表和序列中的所有更改。
开始时间戳取自__ReplicationStart
,结束时间戳取自__ReplicationEnd
(包含最近的安全时间戳)。成功完成后,复制结束时间将保存到__ReplicationStart
,以便下次使用。
参数:
-
staging_schema
(默认是fdw_stage
):远程暂存模式的名称 -
pgstage_schema
(默认是pgsql_stage
):由oracle_migrate_prepare
创建的 PostgreSQL 阶段的名称
您可以在oracle_replication_start
完成后随时调用此函数。
除非数据库中没有触发器或外键约束,否则应在调用此函数时,将配置参数session_replication_role
设置为replica
。这样就不会触发触发器,并且不会检查外键约束。
oracle_replication_catchup
在 Oracle 上使用SERIALIZABLE
隔离级别,因此它可以看到 Oracle 数据库的固定快照,并且数据在 PostgreSQL 端是一致的,即使 Oracle 数据库被其他并发的会话修改。
如果要使用复制进行接近零停机时间的迁移,请在短时间内连续调用两次,并确保在第二次调用期间 Oracle 上没有数据修改活动。第二次追赶完成后,您可以立即将应用程序切换到 PostgreSQL。
函数 oracle_replication_finish
删除 PostgreSQL 和 Oracle 中由oracle_replication_start
创建的所有对象。
这可用于在完成从 Oracle 的迁移后进行清理。
-
server
:Oracle 外部服务器的名称 -
pgstage_schema
(默认是pgsql_stage
):由oracle_migrate_prepare
创建的 PostgreSQL 阶段的名称
限制
并非所有 Oracle 分区选项都受ora_migrator
支持。PostgreSQL 仅支持列表、哈希和范围分区,不支持其他分区策略。此外,不支持使用两列或更多列的分区键进行列表和范围分区。当ora_migrator
遇到一个无法迁移的分区模式时,会将该表迁移到一个非分区表。
复制
ora_migrator
提供了一个从 Oracle 到 PostgreSQL 的简单的基于触发器的复制功能。
这可用于将数据库从 Oracle 迁移到 PostgreSQL,几乎没有停机时间。
操作步骤如下:
-
按照
db_migrator
文档中所述,通过调用db_migrate_prepare
和db_migrate_mkforeign
来准备迁移。 -
暂停 Oracle 数据库上的所有数据修改活动。这是需要的,因为 Oracle 不支持事务性 DDL。
-
然后调用
oracle_replication_start
以设置所有必需的对象。这将在 Oracle 数据库中创建日志表和触发器。 -
然后像往常一样使用
db_migrate_tables
开始数据迁移。一旦
db_migrate_tables
启动,Oracle 数据库上的数据修改活动就可以恢复。迁移将使用SERIALIZABLE
事务隔离级别运行,因此迁移的数据将是一致的。请确保 Oracle 上有足够的 UNDO 存储空间,否则数据迁移可能会失败。
-
使用
db_migrate_constraints
迁移约束和索引;按照db_migrator
文档中所述,迁移其他对象。 -
您可以随时调用
oracle_replication_catchup
,以将更改的数据从 Oracle 传输到 PostgreSQL。这需要为所有受影响的表调用
oracle_catchup_table
,因此要并行化操作,您可以直接为所有受影响的表调用下层的函数。请注意,追赶时不会清理 Oracle 上的日志表。
为避免 PostgreSQL 中的外键约束问题,请在运行
oracle_catchup_table
时,确保将配置参数session_replication_role
设置为replica
。对于接近零停机时间的迁移,在 Oracle 数据库上没有数据修改活动时,还必须执行最后一次
oracle_replication_catchup
调用。调用后,将应用程序切换到 PostgreSQL。 -
要结束复制,请调用
oracle_replication_finish
。这将会删除为复制创建的所有对象。 -
最后,调用
db_migrate_finish
,以删除所有辅助对象。