本文列举了在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
参数为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\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)