作者:何文超,分享 MySQL 和 OceanBase 相关技术博文。 个人博客【CSDN | 雅俗数据库】
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1500 字,预计阅读需要 5 分钟。
1. 故障背景
某客户生产环境从 Oracle 迁移至 OceanBase(文中简称 OB)后,业务投产上线到 OB 侧。
根据业务需求,DBA 在 OB 侧执行扩字段操作,由 varchar2(20) 改为 varchar2(100)。涉及到很简单的一个 DDL 语句(此前在 Oracle 执行多次类似操作,无任何影响),在 OB 执行后,导致业务中断不可用。
1.1 业务影响
-
应用系统持续反馈 Connection is closed 异常 -
INSERT的响应耗时增加 -
无法对 DDL 操作的表进行读写
1.2 紧急处理
-
杀掉 DDL 会话 -
业务侧重启应用服务
下面,笔者将通过复现这个故障,来定位故障原因并介绍后续如何规避。
2. 问题复现
2.1 建表并造数
-- 01:建表(采用上述 Oracle 侧的表结构)
CREATETABLE TEST_ONLINE_DDL (
ID INT,
COL_01 VARCHAR2(20) -- 无约束正常字段
COL_02 VARCHAR2(20) NOTNULLENABLEVALIDATE, -- 启用约束且验证
COL_03 VARCHAR2(20) NOTNULLENABLENOVALIDATE, -- 启用约束不验证历史
);
-- 02: 插入测试数据
INSERTINTO TEST_ONLINE_DDL
VALUES
(1, 'NOVAL_01', 'VALIDATE_01', 'NORMAL_北京'),
(2, 'NOVAL_02', 'VALIDATE_02', ''),
(3, 'NOVAL_03', 'VALIDATE_03', 'NORMAL_上海浦东');
COMMIT;
-- 03: 循环执行 n 次
INSERTINTO TEST_ONLINE_DDL SELECT * FROM TEST_ONLINE_DDL;
COMMIT;
2.2 迁移数据
使用 OMS 将表从 Oracle 迁移到 OB,具体步骤不做阐述。
2.3 表结构对比
迁移后 OB 侧建表语句。
CREATE TABLE"TEST_ONLINE_DDL" (
"ID"NUMBER(*,0),
"COL_01"VARCHAR2(20),
"COL_02"VARCHAR2(20) NOTNULLENABLE,
"COL_03"VARCHAR2(20),
CHECK (("COL_03"isnotnull)) ENABLENOVALIDATE
);
对比发现:
|
|
|
|---|---|
|
|
|
|
|
CHECK (("COL_03" is not null)) ENABLE NOVALIDATE |
对比 Oracle 与 OB 侧的表结构定义发现:
Oracle 中 COL_03 的 NOT NULL ENABLE NOVALIDATE 属性,在 OB 中被转换为 CHECK (COL_NOVALIDATE is not null) ENABLE NOVALIDATE 约束。
2.4 对比 DDL
DDL 如下:
ALTER TABLE TEST_ONLINE_DDL MODIFY COL_01 VARCHAR2(100);
ALTER TABLE TEST_ONLINE_DDL MODIFY COL_02 VARCHAR2(100);
ALTER TABLE TEST_ONLINE_DDL MODIFY COL_03 VARCHAR2(100);
OB 侧字段扩容对比:
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 问题定位
问题的核心源于 迁移工具的结构转换逻辑 与 OceanBase 的 DDL 变更规则 的不兼容。
3.1 OMS 迁移工具的转换规则
OMS 在迁移 Oracle 表结构时,会将列上的 NOT NULL ENABLE NOVALIDATE 属性自动转换为 NOT NULL CHECK 约束(命名类似 %_OBCHECK_%)。这种转换在功能上等价,但 OB 执行 DDL 触发了 Offline DDL 降级规则。
注意:预计在 OMS 4.3.2 版本修复。
3.2 OceanBase 的 DDL 变更规则
对于 CHECK 约束依赖的情况,因用户预期数据发生变长,可能导致不满足 CHECK 约束,OB 会将本应在线的操作(Online DDL)降级为离线操作(Offline DDL)。
特别说明
同类型变长有 CHECK 约束、主键、分区键为 Offline DDL。目前 3.X、4.X 版本皆存在此类问题。
针对 CHECK 约束,后期版本会修复为 Online DDL,目前处于排期中,具体版本官方暂未告知。
离线操作需要重建表结构(table_id发生改变),过程中会持有 MDL 锁,导致所有 DML 操作(如INSERT)阻塞,最终引发业务超时。
注意:对于
CHECK约束执行 DDL 降级为离线操作(Offline DDL),参考官方文档:列类型变更规则[1]
4. 解决方案
针对上述问题,我们制定了两步修复方案,核心是在 OB 侧将 NOT NULL CHECK 约束还原为原生的列 NOT NULL 属性。
4.1 生成原生 NOT NULL 属性的语句
-- OB 侧生成拼接命令,然后执行命令
select
'ALTER TABLE '||C.OWNER||'.'||C.TABLE_NAME||' MODIFY ('||COL.COLUMN_NAME||' NOT NULL ENABLE NOVALIDATE);'
from
dba_constraints c
join
dba_cons_columns col
on c.constraint_name=col.constraint_name
and c.table_name=col.table_name
where c.constraint_type='C'
and c.owner='WMS'
and c.status='ENABLED'
and c.VALIDATED='NOT VALIDATED'
and c.constraint_name like'%_OBCHECK_%'
and c.search_condition like'%is not null%'
orderby c.owner,c.table_name,col.column_name;
4.2 删除冗余的 NOT NULL CHECK 约束
-- OB侧生成拼接命令,然后执行命令
select
'ALTER TABLE '||C.OWNER||'.'||C.TABLE_NAME||' DROP CONSTRAINT '||C.CONSTRAINT_NAME||' ;'
from
dba_constraints c
where c.constraint_type='C'
and c.owner='WMS'
and c.status='ENABLED'
and c.VALIDATED='NOT VALIDATED'
and c.constraint_name like'%_OBCHECK_%'
and c.search_condition like'%is not null%'
orderby c.owner,c.table_name;
4.3 操作时间窗口
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5. 如何判断 DDL 操作为在线操作?
为了避免再次发生执行 DDL 导致的锁表问题,DBA 需要检查在 OB 侧执行的 DDL 语句是否为在线操作(Online DDL)。如果不是,则需要在停服期间执行此 DDL 变更。
如何判断 DDL 是否为 Online DDL?
在 OceanBase 中,判断一次 DDL 操作是否为在线操作(Online DDL)的核心依据之一是 表 ID(TABLE_ID)是否发生变化,这也是实践中最直观有效的验证方式。具体操作如下:
5.1 执行 DDL 前查询表 ID
通过 DBA_OB_TABLE_LOCATIONS 视图获取目标表当前的 TABLE_ID:
SELECT DISTINCT(TABLE_ID)
FROM DBA_OB_TABLE_LOCATIONS
WHERE TABLE_NAME = '目标表名';
5.2 执行 DDL 操作
例如修改字段长度:
ALTER TABLE 目标表名 MODIFY 字段名 VARCHAR2(新长度);
5.3 执行 DDL 后再次查询表 ID
重复步骤 1 的查询语句,对比前后的 TABLE_ID:
-
若 TABLE_ID 保持不变:说明 DDL 操作是在线执行(Online DDL),未触发表结构重建,不会阻塞 DML 操作。 -
若 TABLE_ID 发生变化:说明 DDL 操作被降级为离线操作(Offline DDL),过程中会重建表并持有全局锁,可能导致 DML 阻塞。
更多判断标准可参考 OceanBase 官方文档:如何判断 DDL 操作为在线操作(Online DDL)?[2]
列类型变更规则: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002016923
[2]如何判断 DDL 操作为在线操作(Online DDL): https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000003980674
本文关键字:#OceanBase #DDL #数据类型
活动推荐:12/20 OceanBase 社区 | SQL 遇上 AI · 上海站
活动安排
时间:2025 年 12 月 20 日(周六)13:00 - 17:30
地点:携程集团总部(上海市长宁区金钟路968号)-16号楼-2F10会议室
立即扫码报名,抢占席位!
活动推荐:seekdb 征文活动
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource
🔗 商业支持:https://www.actionsky.com/sqle

