前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PolarDB_PG 迁移至 OB_Oracle 的开源方案

PolarDB_PG 迁移至 OB_Oracle 的开源方案

作者头像
爱可生开源社区
发布于 2025-04-26 12:48:21
发布于 2025-04-26 12:48:21
9400
代码可运行
举报
运行总次数:0
代码可运行

作者:郑增权,爱可生 DBA 团队成员,OceanBase 和 MySQL 数据库技术爱好者。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 2400 字,预计阅读需要 8 分钟

1. 背景

客户存在将 PolarDB PostgreSQL[1] 11.9 (下文以 polardb_pg 代称) 迁移至 OceanBase[2] 4.2.1.10 Oracle (下文以 ob_oracle 代称)租户的需求。

当前 OMS[3] 暂不支持此功能,需要人工迁移,本文将描述迁移的整体思路以及相关的问题处理,为异构数据库之间的迁移方案设计提供参考。

PolarDB PostgreSQL 版本是在 PostgreSQL 数据库的基础上构建的,下文的部分处理步骤会将其视作 PostgreSQL 看待。

2. 步骤概览

迁移范围

表结构 + 全量数据迁移 + 全量数据校验

迁移步骤分工

dbcat[4] 版本:2.1.1

dbcat 可转换的对象范围(polardb_pg -> ob_oracle):表结构、视图、序列,其他对象暂不支持。

  • 用户迁移:人工创建
  • 角色迁移:脚本处理
  • 权限迁移:脚本处理
  • 表结构迁移:dbcat 工具
  • 视图迁移:dbcat 工具
  • 序列迁移:dbcat 工具
  • 外键迁移:dbcat 工具 + 脚本处理
  • 其他对象迁移:业务侧自行迁移
  • 数据迁移:DataX[5]
  • 数据校验:脚本处理

3. 用户迁移

  1. polardb_pg 的一个用户可以对应多个 schema。
  2. ob_oracle 租户的一个用户只能对应一个 schema(即,用户名就是 schema)。
  3. 当 polardb_pg 迁移至 ob_oracle 时,一般而言,polardb_pg 端的 schema_name = ob 端的用户名。
    • 特殊项: PUBLIC 等 OB 端默认角色不可作为 OB 端的用户名,需改成新的用户名。
  4. polardb_pg 待迁移用户拥有的角色也需要迁移至 ob_oracle 端。

4. 权限转换

ob_oracle 端权限[6] 分为"对象权限"和"系统权限"两大类,而 polardb_pg 端权限[7] 分类则更多一些。

权限转换思路

  1. 相同的权限无需转换,直接授权即可。
  2. polardb_pg 端特有的权限,在 ob_oracle 端授予相近的权限,或组合权限以实现对应的功能。
    • 比如 polardb_pg 端的 TRUNCATE 权限,在 ob_oracle 端则是用户拥有表的 DROP 权限就可以进行 TRUNCATE TABLE 操作。

5. 表结构转换

5.1 dbcat 转换效率提升

请根据机器实际内存进行调整。

  1. -Xms8G:初始堆内存为 8GB。
  2. -Xmx16G:最大堆内存为 16GB。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@evan_zheng-server bin]# grep Xms dbcat
JAVA_OPTS="$JAVA_OPTS -Xms8G -Xmx16G -XX:+UseG1GC -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M"

5.2 引号问题

5.2.1 问题描述
  1. dbcat 转换默认会将 库名、表名、列名、约束名 带上双引号。
  2. 若在 ob_oracle 端执行 DDL 带上双引号会严格保留双引号中指定的格式(包括大小写),可能导致执行 SQL 时发生找不到表、列等问题。
5.2.2 解决方法

dbcat 转换时加上 --no-quote 可以产生不带引号的 DDL 语句,示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dbcat convert -H 10.186.64.61 -P 5432 -u $pg_user -p $password -D postgres --schema $schema --from pgsql11 --to oboracle420 --no-quote --table '*' -f /dbcat_path > dbcat_all_tables_$(date +%Y%m%d_%H%M%S).log 2>&1

5.3 外键

5.3.1 问题描述

dbcat 表结构转换时外键与表结构同时生成在一个文件,外键不应在数据迁移前创建,会导致数据迁移出错。

5.3.2 解决方法

将外键从表结构文件中提取并保存到其他文件。

方式一:若外键数量少,且关联的表数据量小,在迁移完数据之后可以直接进行创建,示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ALTER TABLE $pg_user.$table_name ADD CONSTRAINT "$fk_name" FOREIGN KEY ("$fk_column") REFERENCES $pg_user.$table_name ("$primary_column");

方式二:若外键数量多,且关联的表数据量大,可以通过 ENABLE NOVALIDATE (不检查现有数据是否满足外键条件,新插入或更新的数据必须遵守外键约束。)格式快速创建外键,示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ALTER TABLE $pg_user.$table_name ADD CONSTRAINT "$fk_name" FOREIGN KEY ("$fk_column") REFERENCES $pg_user.$table_name ("$primary_column") ENABLE NOVALIDATE;

5.4 包含 oid 字段属性的表

5.4.1 问题描述

polardb_pg 存在一种 PostgreSQL数据库 特有的数据类型 oid,包含 oid 字段属性的表无法通过 dbcat 转换,dbcat 在转换表结构时会直接将表忽略,表结构示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
      column_name      |          data_type          | character_maximum_length | is_nullable | column_default |     primary_key     
-----------------------+-----------------------------+--------------------------+-------------+----------------+---------------------
 id                    | character varying           |                       36 | NO          |                | PRIMARY KEY (id)
 content               | oid                         |                          | YES         |                | 
(2 rows)
5.4.2 解决方法

源端将其改造为 bigint 再通过 dbcat 转换。

5.5 基于 oid 创建的索引

5.5.1 问题描述

如下示例中,(oid): 表示索引是基于表的 oid 列创建的。oid 通常是 PostgreSQL 中的一种特殊列类型,用于存储对象的唯一标识符,一般由 PostgreSQL 数据库自动生成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 schemaname |        tablename         |        indexname        | tablespace |                                             indexdef                         
                    
------------+--------------------------+-------------------------+------------+------------------------------------------------------------------------------
 $schema     | $table_name             | pg_oid_12345_index |            | CREATE UNIQUE INDEX pg_oid_12345_index ON $schema.$table_name USING btree (oid)
5.5.2 解决方法

OceanBase 数据库中没有 oid 这种存储对象的唯一标识符,在 dbcat 转换完的文件中直接移除这一类索引。

5.6 boolean 字段转换

5.6.1 问题描述

dbcat 会将 polardb_pg 中的 boolean 字段转成 ob_oracle 端的 NUMBER(1),polardb_pg 端给 boolean 赋值可能是(t,f,n),迁移数据时,尝试往 NUMBER(1) 插入 (t,f,n)会因为字段属性不符而报错。

5.6.2 解决方法
  1. 在 ob_oracle 目标端将 NUMBER(1) 替换为 CHAR(5) 以提高字段兼容性
  2. 程序代码需做调整,比如原本查询语句是:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id from table1 where flag = t;

需改成(加上单引号):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id from table1 where flag = 't';

6. DataX 数据迁移

6.1 DataX 迁移效率提升

6.1.1 DataX 配置参数

请根据机器实际内存进行调整。

  1. -Xms16g:初始堆内存为 16GB。
  2. -Xmx32g:最大堆内存为 32GB。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grep "DEFAULT_JVM" /opt/module/datax/bin/datax.py | grep "Xms"
DEFAULT_JVM = "-Xms16g -Xmx32g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%s/log" % (DATAX_HOME)
6.1.2 DataX json 配置参数
  1. 参数根据实际调整,关键配置作出注释。
  2. 有主键的表需指定 splitPK。

特殊事项:联合主键不符合 json 文件格式,需当作无主键表迁移。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "job": {
        "setting": {
            "speed": {
                // 控制数据传输速度
                "channel": 32// 并发通道(线程)数;值越大并行度越高,但可能增加资源压力
            },
            "errorLimit": {
                "record": 1000, // 允许的最大错误记录数,超过则作业失败
                "percentage": 0// 允许的错误记录百分比(0 表示不按百分比限制)
            }
        },
        "content": [
            {
                "reader": {
                    // 数据源(读取数据)的配置
                    "name": "postgresqlreader",
                    "parameter": {
                        "username": "$pg_user",
                        "password": "$password",
                        "column": ["id", "version"],
                        "connection": [
                            {
                                "table": ["$schema.$table_name"],
                                "jdbcUrl": ["jdbc:postgresql://10.186.64.61:5432/postgres?useUnicode=true&characterEncoding=utf8"]
                            }
                        ],
                        "splitPK": "id"// 数据分片主键,用于并行读取(按 id 分片)
                    }
                },
                "writer": {
                    // 数据目标(写入数据)的配置
                    "name": "oceanbasev10writer",
                    "parameter": {
                        "obWriteMode": "insert",
                        "column": ["id", "version"],
                        "connection": [
                            {
                                "table": ["$table_name"],
                                "jdbcUrl": "jdbc:oceanbase://10.186.64.161:2883/$schema_name?useLocalSessionState=true&allowBatch=true&allowMultiQueries=true&rewriteBatchedStatements=true"// OceanBase JDBC 连接字符串,包含批量操作优化参数
                            }
                        ],
                        "username": "SYS@ora_tenant#cluster",
                        "password": "$password",
                        "writerThreadCount": 10, // 写入线程数,控制写入并行度
                        "batchSize": 1000, // 每批次写入的记录数,优化性能
                        "memstoreThreshold": "0.9"
                    }
                }
            }
        ]
    }
}

6.2 数据迁移异常时的处理机制

6.2.1 问题描述

本文的数据迁移任务,分为主任务和多个子任务,主任务是所有需迁移的表的汇总项,子任务是每个表一个任务,启动主任务之后会自动拉起子任务,子任务会按照配置文件依次执行。

DataX 迁移数据时存在某些数据无法迁移,但是不会报错终止任务而是反复重试的行为,这会导致持续打印无效日志占用空间,且阻碍后续任务运行。

6.2.2 解决方法

引入监控脚本,在 OB 端间隔一秒查询一次当前迁移的表和行数,当发现当前迁移的表 5 分钟内行数没有变化时,会自动 kill 掉对应的子任务进程并记录到日志,示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[2025-04-17 10:23:18] ------------------------
[2025-04-17 10:23:24] 开始检查
[2025-04-17 10:23:24] 总表数量: 4454
[2025-04-17 10:23:24] 当前表: $table_name
[2025-04-17 10:23:24]4228 个表
[2025-04-17 10:23:24]OB数据库)查询记录数: 0
[2025-04-17 10:23:24] 检查表行数和kill卡住的表_脚本执行剩余时间: 55小时 11分钟

7. 性能监控

  1. PolarDB PostgreSQL 数据库的平台监控。
  2. OceanBase 数据库的 OCP 平台监控。
  3. 主机资源监控。

8. 结论

  1. 异构数据库迁移需考虑两者差异性,测试环境中进行方案验证,再在生产环境进行实施和优化,建议生产环境至少进行一至两轮模拟迁移之后再正式进行割接。
  2. 非增量迁移,为保证数据一致性,停业务并锁定两端用户后再迁移数据。

参考资料

[1]

PolarDB PostgreSQL 版: https://www.aliyun.com/product/apsaradb/polardbpg

[2]

OceanBase 企业版: https://www.oceanbase.com/product/oceanbase

[3]

OceanBase Migration Service: https://www.oceanbase.com/product/oms

[4]

dbcat: https://www.oceanbase.com/docs/enterprise-oceanbase-database-cn-1000000000749015

[5]

DataX: https://github.com/alibaba/datax

[6]

ob_oracle 端权限: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000220864

[7]

polardb_pg 端权限: https://help.aliyun.com/zh/polardb/polardb-for-oracle/warpaman72ax09gk

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱可生开源社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 背景
  • 2. 步骤概览
    • 迁移范围
    • 迁移步骤分工
  • 3. 用户迁移
  • 4. 权限转换
    • 权限转换思路
  • 5. 表结构转换
    • 5.1 dbcat 转换效率提升
    • 5.2 引号问题
      • 5.2.1 问题描述
      • 5.2.2 解决方法
    • 5.3 外键
      • 5.3.1 问题描述
      • 5.3.2 解决方法
    • 5.4 包含 oid 字段属性的表
      • 5.4.1 问题描述
      • 5.4.2 解决方法
    • 5.5 基于 oid 创建的索引
      • 5.5.1 问题描述
      • 5.5.2 解决方法
    • 5.6 boolean 字段转换
      • 5.6.1 问题描述
      • 5.6.2 解决方法
  • 6. DataX 数据迁移
    • 6.1 DataX 迁移效率提升
      • 6.1.1 DataX 配置参数
      • 6.1.2 DataX json 配置参数
    • 6.2 数据迁移异常时的处理机制
      • 6.2.1 问题描述
      • 6.2.2 解决方法
  • 7. 性能监控
  • 8. 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档