本文总结剖析了 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;
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 中 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 中分区表搬迁到 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);
总结
以上总结剖析了 3 种 Oracle 目标和 OB 目标不兼容时的处理办法和提早计算发现的操作方式,在搬迁条件早发现这类问题能有用防止在搬迁进程中报错的问题。
更多技术文章,请拜访:opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理渠道,掩盖开发至出产环境的 SQL 审阅和管理。支撑主流的开源、商业、国产数据库,为开发和运维提供流程主动化才能,提升上线效率,进步数据质量。