本文列举了在Oracle迁移到PolarDB过程中需重点关注的事项。请在迁移前仔细阅读,以确保迁移过程的顺利进行。
序列值同步
问题描述
Oracle中的序列值会自动同步到PolarDB中吗?如何同步?
分析
PolarDB无法自动同步序列值。PolarDB的逻辑复制完全兼容PostgreSQL协议,但序列值目前未被纳入PostgreSQL协议的逻辑复制范围。
- 在进行结构迁移时,数据库会一次性同步源库当前时刻的序列值,假设为Q1。在随后的全量数据和增量数据同步过程中,源库的序列值可能会继续增长,例如增长到Q2,而目标库的序列值保持不变,仍为Q1。然而,数据库中的表数据会实时保持两边的同步。 
- 在数据库割接前的增量同步期间,源库的序列值为Q2,目标库的序列值为Q1,这可能引发冲突。例如,如果从目标库的Q1序列中取一个值并写入表中,由于表数据是从源库同步过来的,Q1可能已经被使用过,从而导致主键唯一约束冲突。 
解决方案
- 方案一:使用同步Sequence - 在增量写入基本信息页面单击同步Sequence,此时DTS(数据传输服务)会生成序列同步语句,执行序列值的同步操作。详细操作可参考更新目标库的Sequence值。 
- 方案二:手动同步序列值 - 参考自建Oracle迁移至PolarDB PostgreSQL版(兼容Oracle)中提供的手动同步序列值到PolarDB的方案,按照文档要求手动进行序列值的同步。 
编码设置
问题描述
在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中, - CHAR和- VARCHAR类型的精度以字节数表示。
- 在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参数为off,可以确保正向迁移过程中不会出现问题。- 方案二:在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\0和- dts会存在数据冲突,在迁移至目标数据库时,仅保留一条数据将导致数据的丢失。
空串迁移
问题描述
在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)