本文总结剖析了 3 种 Oracle 目标和 OB 目标不兼容时的处理办法和提早计算发现的操作方式,在搬迁条件早发现这类问题能有用防止在搬迁进程中报错的问题。

作者:余复兴,爱可生 DBA 团队成员,热衷技术分享、编写技术文档。

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

本文共 1500 字,估计阅读需求 5 分钟。

布景介绍

在进行国产化改造进程中,咱们需求将 Oracle 数据库搬迁到 OceanBase(Oracle 模式)数据库,尽管 OceanBase 关于 Oracle 兼容性已经满足好,但依旧还有一些特殊语法或目标需求单独处理,下面是遇到的一些不完全兼容目标的处理逻辑。

Oracle 中 LOB 类数据搬迁到 OB 时的处理逻辑

Oracle 中 CLOB 和 BLOB 类型均可到达 4G 巨细(以 Oracle 11.2 为例),而 OceanBase 数据库当时版别(3.2.3.x)所支撑的大目标数据类型的信息如下表所示:

类型 BLOB CLOB
长度 变长 变长
自界说长度上限(字符 48MB 48MB
字符集 BINARY 与租户字符集一致

考虑到从 Oracle 搬迁到 OceanBase,如果触及 LOB 类字段,或许会存在当 LOB 数据大于 48M 时数据丢掉的问题,需求提早发现这类数据并进行处理。

2.1 找到 Oracle 中 LOB 数据最大长度

咱们能够构建一个实验生成 CLOB 及 BLOB 类型数据,运用 Oracle 自带的 DBMS_LOB 包获取对应类型的最大值。

2.1.1 构建包含LOB类型的数据表

CREATE TABLE t_lob(
    c_ID NUMBER,
    c_clob CLOB,
    c_blob BLOB
);

2.1.2 创立造数据存储进程

随机刺进 100 条记载到 t_lob 表。

CREATE OR REPLACE PROCEDURE insert_random_lob_data AS
BEGIN
  DECLARE
    l_random_string VARCHAR2(10000);
    l_random_blob BLOB;
  BEGIN
    FOR i IN 1..100 LOOP
      l_random_string := dbms_random.string('U', dbms_random.value(1, 10000));
      dbms_lob.createtemporary(l_random_blob, TRUE);
      dbms_lob.writeappend(l_random_blob, LENGTH(l_random_string), utl_raw.cast_to_raw(l_random_string));
      INSERT INTO t_lob(c_ID, c_clob, c_blob)
      VALUES(i, l_random_string, l_random_blob);
      dbms_lob.freetemporary(l_random_blob);
    END LOOP;
    COMMIT;
  END;
END;
/

2.1.3 查询该表中 CLOB 和 BLOB 字段的最大值

SELECT MAX(DBMS_LOB.GETLENGTH(C_CLOB)) AS LONGEST_CLOB,
       MAX(DBMS_LOB.GETLENGTH(C_BLOB)) AS LONGEST_BLOB
  FROM T_LOB;

Oracle 中部分不兼容目标搬迁到 OceanBase 的处理方式

2.2 获取整个数据库中 LOB 字段值较大的清单

扫除了系统用户,获取 LOB 字段清单后再根据清单中的 LOB 字段单独剖析其最大值。

SELECT COL.OWNER,
       COL.TABLE_NAME,
       COL.COLUMN_NAME,
       COL.DATA_TYPE,
       COL.AVG_COL_LEN,
       COL.CHAR_LENGTH,
       TAB.NUM_ROWS
  FROM DBA_TABLES TAB, DBA_TAB_COLUMNS COL
 WHERE TAB.OWNER = COL.OWNER
   AND TAB.TABLE_NAME = COL.TABLE_NAME
   AND COL.DATA_TYPE IN ('CLOB', 'BLOB')
   AND COL.OWNER NOT IN ('SYS', 'SYSTEM')
   AND COL.OWNER IN
       (SELECT USERNAME FROM DBA_USERS WHERE ACCOUNT_STATUS = 'OPEN')
   AND COL.TABLE_NAME NOT LIKE 'BIN%';

Oracle 中部分不兼容目标搬迁到 OceanBase 的处理方式

Oracle 中 disable 束缚在 OMS 搬迁进程中的处理逻辑

在对 Oracle 中的束缚类非表目标做一致性校验时,发现部分束缚在 OMS 搬迁完成后丢掉了,需求剖析其 OMS 丢掉的原因。

3.1 问题剖析

从 OMS 界面中获取 DDL 的句子能够看到有 2 个 WARN,且类型是 DISCARD,表明 OMS 判断其是 DISABLE 状况的束缚,直接挑选了放弃掉。

-- [WARN] [DISCARD] CONSTRAINT "PK_T_PARTKEY_IS_PK" PRIMARY KEY ("CRT_DTTM") DISABLE NOVALIDATE -> [NULL]
-- [WARN] [DISCARD] CHECK ("ACT_ID" IS NOT NULL) DISABLE NOVALIDATE -> [NULL]
CREATE TABLE "T_PARTKEY_IS_PK" (
    "ACT_ID" NUMBER(10,0),
    "SRT_ID" NUMBER(10,0),
    "SRT_ORIGNAL_ID" NUMBER(10,0),
    "CRT_DTTM" DATE,
    "LASTUPT_DTTM" DATE
)

3.2 问题定论

Oracle 侧处于 DISABLE 状况的束缚经过 OMS 搬迁时会被放弃,不会在 OB 侧创立,在对束缚目标比对时,需求额定注意 Oracle 端束缚的 status 是否处于 DISABLE 状况,自身对事务和功能没有影响。

3.3 束缚校验时提早扫除 DISABLE 的束缚

能够经过以下句子观测源端 Oracle 束缚状况。

-- 手工将T_PARTKEY_IS_PK表的束缚都disable
ALTER TABLE ZHENXING.T_PARTKEY_IS_PK DISABLE NOVALIDATE CONSTRAINT PK_T_PARTKEY_IS_PK;
ALTER TABLE ZHENXING.T_PARTKEY_IS_PK DISABLE CONSTRAINT SYS_C0011109;
SELECT OWNER,
       TABLE_NAME,
       CONSTRAINT_NAME,
       CONSTRAINT_TYPE,
       INDEX_NAME,
       STATUS
  FROM DBA_CONSTRAINTS
 WHERE OWNER = 'ZHENXING'
   AND TABLE_NAME = 'T_PARTKEY_IS_PK';

Oracle 中部分不兼容目标搬迁到 OceanBase 的处理方式

Oracle 中分区表搬迁到 OB 后,带有的主动分区特点丢掉

主动分区特点是 Oracle 11g 的特性,能够用 INTERVAL 语法根据天、月、年做主动分区创立。 在经过 OMS 搬迁到 OB 后,发现主动分区特点丢掉了,会导致当分区未主动创立时导致新增数据无法写入分区表,导致报错。

4.1 问题剖析

从 OMS 界面中获取 DDL 的句子能够看到有 1 个 WARN,且类型是 DISCARD,表明 OMS 判断其不完全兼容,直接挑选了放弃掉。

-- OMS 搬迁表结构时记载的WARN信息,表明主动分区特点因为不兼容会主动DISCARD放弃
[WARN] [DISCARD]  INTERVAL (NUMTOYMINTERVAL (1,'MONTH')) -> [NULL]

4.2 问题定论

所以在 Oracle 搬迁到 OB 前,需求把 Oracle 端存在主动分区特点的表提早找出,防止因为搬迁到 OB 后分区为未主动创立导致的数据无法刺进的报错,而且找出这类分区后,先在 Oracle 端创立满足的多分区,防止搬迁进程中源端分区数添加导致比对不一致的情况。并记载清单告知事务开发待后续用其他方式定时生成新分区。

4.3 如何找出 Oracle 中主动分区的表

4.3.1 Oracle 侧模拟主动分区

-- 创立根据天的主动分区表
SQL> create table interval_sales (
    prod_id number(6),
    time_id date)
    partition by range (time_id)
    INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
    (partition p1 values less than (to_date('2015-01-01','yyyy-mm-dd')));
-- 查询当时分区,默许生成了1个界说好的分区
SQL> SELECT TABLE_NAME, PARTITION_NAME
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME = 'INTERVAL_SALES';
TABLE_NAME                       PARTITION_NAME
------------------------------ ------------------------------
INTERVAL_SALES                       P1
-- 刺进数据(不在默许分区内)
SQL> INSERT INTO INTERVAL_SALES VALUES(001, TO_DATE('2015-02-01', 'yyyy-mm-dd'));
-- 主动生成了新分区
TABLE_NAME                       PARTITION_NAME
------------------------------ ------------------------------
INTERVAL_SALES                       P1
INTERVAL_SALES                       SYS_P221
-- 单独查看该分区数据(验证数据确实存在新分区)
SQL> SELECT * FROM INTERVAL_SALES PARTITION(SYS_P221);
   PROD_ID TIME_ID
---------- ---------
         1 01-FEB-15

4.3.2 计算 Oracle 侧有哪些表是主动分区的表

/*
PARTITION_COUNT: Number of partitions in the table. For interval partitioned tables, the value of this column is always 1048575.
*/
SELECT T1.OWNER,
       T1.TABLE_NAME,
       T1.INTERVAL,
       T1.PARTITIONING_TYPE,
       T1.PARTITION_COUNT,
       T1.SUBPARTITIONING_TYPE      AS SUB_TYPE,
       T1.SUBPARTITIONING_KEY_COUNT SUB_COUNT,
       T1.STATUS
  FROM DBA_PART_TABLES T1
 WHERE 1 = 1
   AND TABLE_NAME NOT LIKE 'BIN%'
   AND (INTERVAL IS NOT NULL OR PARTITION_COUNT = 1048575);

Oracle 中部分不兼容目标搬迁到 OceanBase 的处理方式

总结

以上总结剖析了 3 种 Oracle 目标和 OB 目标不兼容时的处理办法和提早计算发现的操作方式,在搬迁条件早发现这类问题能有用防止在搬迁进程中报错的问题。

更多技术文章,请拜访:opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理渠道,掩盖开发至出产环境的 SQL 审阅和管理。支撑主流的开源、商业、国产数据库,为开发和运维提供流程主动化才能,提升上线效率,进步数据质量。