Oracle迁移前重要注意事项

本文列举了在Oracle迁移到PolarDB过程中需重点关注的事项。请在迁移前仔细阅读,以确保迁移过程的顺利进行。

序列值同步

问题描述

Oracle中的序列值会自动同步到PolarDB中吗?如何同步?

分析

PolarDB无法自动同步序列值。PolarDB的逻辑复制完全兼容PostgreSQL协议,但序列值目前未被纳入PostgreSQL协议的逻辑复制范围。

  • 在进行结构迁移时,数据库会一次性同步源库当前时刻的序列值,假设为Q1。在随后的全量数据和增量数据同步过程中,源库的序列值可能会继续增长,例如增长到Q2,而目标库的序列值保持不变,仍为Q1。然而,数据库中的表数据会实时保持两边的同步。

  • 在数据库割接前的增量同步期间,源库的序列值为Q2,目标库的序列值为Q1,这可能引发冲突。例如,如果从目标库的Q1序列中取一个值并写入表中,由于表数据是从源库同步过来的,Q1可能已经被使用过,从而导致主键唯一约束冲突。

解决方案

编码设置

问题描述

在Oracle中可能使用到GBK或UTF8编码,如何确认PolarDB的编码选择?

解决方案

在Oracle中,中文字符集通常采用GBK或UTF8。但是,在迁移至PolarDB的过程中,建议选择UTF8,因为UTF8具备更佳的兼容性。具体原因如下:

  • 避免编码冲突风险:PolarDB不推荐使用GBK作为服务端字符集。由于GBK字符集部分字符的编码范围与ASCII码存在冲突,这可能导致数据迁移过程中出现编码错误。

  • 防止乱码插入:Oracle采用GBK字符集时允许插入无效的GBK编码,这可能导致数据读取时出现乱码。然而,PolarDB不支持这一特性,因此在使用GBK字符集是可能存在数据无法插入的风险。

综上,建议在迁移过程中选择UTF8编码,以确保数据兼容性和顺利迁移。

库表名大小写

问题描述

在Oracle数据库中,表名和列名默认大写,而在PolarDB中,表名和列名则默认小写。针对这种差异,PolarDB如何处理名称冲突?

解决方案

Oracle默认将属性名(如Schema、TABLE、Column等)转换为大写,而PolarDB PostgreSQL版(兼容Oracle)默认将属性名转换为小写。在处理Oracle到PolarDB PostgreSQL版(兼容Oracle)的迁移任务时,DTS将根据实际业务情况采取相应的默认处理方案,具体方案如下:

  • 默认大写转小写(未使用引号)

    • 适用场景:不使用双引号(即不区分大小写),在Oracle中默认使用大写名称。

    • 处理方案:DTS默认将所有属性名迁移到PolarDB PostgreSQL版(兼容Oracle)时转换为小写。切换至PolarDB PostgreSQL版(兼容Oracle)后,同样无需使用双引号,数据库默认使用小写名称,无需进行业务改造或特殊配置,支持无缝切换。

  • 保持原有大小写(使用引号)

    • 适用情况:在Oracle中使用大小写混合的属性名,并通过双引号防止自动转换。

    • 处理方案:DTS默认将属性名保持原有大小写(需选择关闭具体映射)。切换至PolarDB PostgreSQL版(兼容Oracle)后,继续使用双引号,无需进行业务改造或特殊配置,支持业务无缝切换。

  • 查询重试

    PolarDB中默认带有大写的重试功能,即一个表如果是大写表,那么通过纯大写或者纯小写都可以查到这个表。

CHAR和VARCHAR精度语义

问题描述

Oracle和PolarDB中默认的VARCHAR(20)的含义是否一致?

分析

Oracle和PolarDB中默认的VARCHAR(20)的含义不一致。

  • 在Oracle中,CHARVARCHAR类型的精度以字节数表示。

  • PolarDB PostgreSQL版(兼容Oracle)中,CHAR和 VARCHAR类型的精度默认以字符数表示。

  • PolarDB PostgreSQL版(兼容Oracle)提供参数polar_default_char_length_semantics,能够影响CHAR和 VARCHAR类型的精度。默认值为off,即字符类型,如果设置为on,则会转为字节类型。

    说明

    您可以通过控制台修改polar_default_char_length_semantics参数,详细操作可参考设置集群参数

解决方案

  • polar_default_char_length_semantics 参数为on,可能遇到的问题:

    • 业务环境:Oracle中 CHAR(10)使用GBK字符集,PolarDB PostgreSQL版(兼容Oracle)中 CHAR(10)使用UTF8字符集。

    • 问题:在Oracle到PolarDB PostgreSQL版(兼容Oracle)的正向同步中,Oracle写入字符串“测试测试测”,实际占用2 × 5即10字节,恰好达到Oracle定义的最大字节数,若超出则会报错。

    • 解决方案:

      方案一:设置polar_default_char_length_semantics 参数为on,可以确保正向迁移过程中不会出现问题。

      方案二:在PolarDB PostgreSQL版(兼容Oracle)中扩大表定义的长度。

  • polar_default_char_length_semantics 参数为off,可能遇到的问题:

    • 业务环境:Oracle中 CHAR(10)使用GBK字符集,PolarDB PostgreSQL版(兼容Oracle)中 CHAR(10)使用UTF8字符集。

    • 问题:在PolarDB PostgreSQL版(兼容Oracle)到Oracle的反向同步中,PolarDB PostgreSQL版(兼容Oracle)写入字符串“测试”,实际占用字符数为2 + 8,总计10字符,转换为字节后得2 × 3 +8,即14字节,超过Oracle定义的10字节,导致数据截断报错。

    • 解决方案:

      方案一:扩大源Oracle中的字节长度,以容纳更大的字符串长度。

      方案二:在DTS中通过ETL任务配置字符截断,截断多余字符,详细操作请参考在DTS迁移或同步任务中配置ETL

无主键/唯一键表

问题描述

在Oracle中,如果存在无主键或唯一键的表,该如何处理?是否会对数据校验产生影响?

解决方案

针对无主键或唯一键表,DTS无法确保数据的一致性,目标端可能出现多条数据。根据不同业务需求,提供以下两种方案供您选择。

  • 如果不强烈要求无PK/UK表数据一致性,或者计划业务自行去重。正常迁移即可。

  • 如果要求数据一致性,可以将Oracle中的ROWID作为目标端的隐藏主键(非空唯一键),在业务切换前删除新增列即可。在DTS控制台配置为无主键表/无唯一键表增加隐藏主键,详细操作请参考自建Oracle迁移至PolarDB PostgreSQL版(兼容Oracle)。迁移任务结束后,请点击相应按钮以删除隐藏主键,这样可以对这些数据进行迁移和校验。请注意,当前无主键表暂不支持数据校验。

迁移过程中的\0字符处理

问题描述

在Oracle数据中存在隐藏的\0数据,迁移过程中是否会造成问题?

解决方案

PolarDB PostgreSQL版(兼容Oracle)无法存在\0字符,DTS内部逻辑会将\0字符去除。

  • 对于普通字段,此处理逻辑可能导致字符迁移后前后不等价,因此需要您提前确认。

  • 如果主键字段出现\0字符,此处理逻辑可能会导致数据不一致。例如主键id:dts\0dts会存在数据冲突,在迁移至目标数据库时,仅保留一条数据将导致数据的丢失。

空串迁移

问题描述

在Oracle中,空串''与NULL被视为同一对象。PolarDB对此是否兼容?

解决方案

Oracle作为早期数据库,VARCHAR/VARCHAR2类型不遵循SQL标准,将空字符串视为NULL值进行处理。PolarDB通过参数 polar_empty_string_is_null_enable 兼容Oracle的空串行为。该功能默认开启,如确认不再需要此功能,可在控制台中进行关闭,详细操作可参考设置集群参数

时区设置

问题描述

如何设置PolarDB时区?其影响有哪些?

解决方案

在PolarDB中,时区的默认值为UTC。这将导致数据库中所有当前时间均以UTC为基准。

举例而言,以中国北京时间(2024年12月3日 18:13:34 )为例查询:

SELECT * FROM now();

返回结果如下:

              now               
--------------------------------
 2024-12-03 10:13:34.018557 +00
(1 row)

如需将时区调整为中国北京时间,请在控制台中设置参数timezone,设置为PRC时,表示使用中国北京时区,详细操作可参考设置集群参数。重新查询当前时间:

SELECT * FROM now();

设置时区后,时间延迟8小时,返回结果如下:

              now               
--------------------------------
 2024-12-03 18:14:34.841027 +08
(1 row)

INTEGER类型范围

问题描述

Oracle中INTEGER类型为NUMBER(38),而在PolarDB PostgreSQL版(兼容Oracle)中INTEGER类型为32位整型。对此PolarDB如何实现兼容?

解决方案

在Oracle中若存在形如CAST(val AS INTEGER) 需要改写为CAST(val AS NUMBER(38))以避免out of integer报错。

例如,PolarDB PostgreSQL版(兼容Oracle)中如下范围将会导致out of integer报错,而Oracle可以正常执行。

SELECT CAST(99999999999 AS INTEGER) FROM dual;
  • Oracle返回结果如下:

       CAST(99999999999ASINTEGER)
    _____________________________
                      99999999999
  • PolarDB PostgreSQL版(兼容Oracle)返回结果如下:

    ERROR:  integer out of range

PolarDB PostgreSQL版(兼容Oracle)中将上述语句修改为:

SELECT CAST(99999999999 AS NUMBER(38)) FROM dual;

PolarDB PostgreSQL版(兼容Oracle)返回结果如下:

   numeric   
-------------
 99999999999
(1 row)