前言
offline ddl 会锁表并且执行时间通常很长,对业务影响较大,需要明确与online ddl区分开,一般查下文档后还需要再次验证下结论是否准确,近期发现增加列长 DECIMAL 时而是online ddl时而是offline ddl 的现象
结论
结论放前面 :decimal 类型特殊,增加列长操作超过阈值就是 offline ddl操作,比如从 3->9 就是 online ddl,3->10就是 offline ddl操作,修改小数位为 offline ddl 操作
环境
版本:OceanBase 4.3.5.5
模式:mysql
测试
create table test1 (c1 int primary key,c2 DECIMAL(6,2));
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
alter table test1 modify c2 DECIMAL(7,2);
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
alter table test1 modify c2 DECIMAL(19,2);
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
alter table test1 modify c2 DECIMAL(19,3);
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
obclient(dc@(none))[dc]> create table test1 (c1 int primary key,c2 DECIMAL(6,2));
Query OK, 0 rows affected (0.213 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
+----------+
| table_id |
+----------+
| 1082169 |
+----------+
1 row in set (0.223 sec)
obclient(dc@(none))[dc]> alter table test1 modify c2 DECIMAL(7,2);
Query OK, 0 rows affected (0.180 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
+----------+
| table_id |
+----------+
| 1082169 |
+----------+
1 row in set (0.018 sec)
obclient(dc@(none))[dc]> alter table test1 modify c2 DECIMAL(19,2);
Query OK, 0 rows affected (1.040 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
+----------+
| table_id |
+----------+
| 1082170 |
+----------+
1 row in set (0.018 sec)
obclient(dc@(none))[dc]> alter table test1 modify c2 DECIMAL(19,3);
Query OK, 0 rows affected (0.939 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='test1';
+----------+
| table_id |
+----------+
| 1082171 |
+----------+
1 row in set (0.018 sec)
如上,c2列从 DECIMAL(6,2) → DECIMAL(7,2),是online ddl,DECIMAL(7,2) → DECIMAL(19,2)是offline ddl
找了下435文档,增加列长是online ddl,跟测试结果冲突
| 分支 | 条件 | 结果 |
|---|---|---|
| 第一个 if | 源列类型为:number、bit、char、varchar、varbinary、text、blob、timestamp、datetime、任意整数类型、json | 在线:不设置 is_offline,保持可在线 DDL |
| else if | 源列是 decimal int,且 scale (小数位)不变,且 精度对应的 decimal int 内部类型不变(get_decimalint_type(precision) 相同) | 在线:同样不设置 is_offline |
| else | 以上都不满足(例如 decimal int 改了 scale 或改了「精度档位」,或其他未列出的类型扩大长度) | 离线:is_offline = true,需要离线 DDL |
源码如上,decimal 比较特殊,超过阈值就是offline,比如从3->9就是online,3->10就是offline
create table dc_test1 (c1 int primary key,c2 DECIMAL(3,2));
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test1';
alter table dc_test1 modify c2 DECIMAL(9,2);
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test1';
create table dc_test2 (c1 int primary key,c2 DECIMAL(3,2));
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test2';
alter table dc_test2 modify c2 DECIMAL(10,2);
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test2';
obclient(dc@(none))[dc]> create table dc_test1 (c1 int primary key,c2 DECIMAL(3,2));
Query OK, 0 rows affected (0.149 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test1';
+----------+
| table_id |
+----------+
| 1082176 |
+----------+
1 row in set (0.032 sec)
obclient(dc@(none))[dc]> alter table dc_test1 modify c2 DECIMAL(9,2);
Query OK, 0 rows affected (0.167 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test1';
+----------+
| table_id |
+----------+
| 1082176 |
+----------+
1 row in set (0.018 sec)
obclient(dc@(none))[dc]>
obclient(dc@(none))[dc]> create table dc_test2 (c1 int primary key,c2 DECIMAL(3,2));
Query OK, 0 rows affected (0.142 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test2';
+----------+
| table_id |
+----------+
| 1082177 |
+----------+
1 row in set (0.018 sec)
obclient(dc@(none))[dc]> alter table dc_test2 modify c2 DECIMAL(10,2);
Query OK, 0 rows affected (1.001 sec)
obclient(dc@(none))[dc]> select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='dc_test2';
+----------+
| table_id |
+----------+
| 1082178 |
+----------+
1 row in set (0.017 sec)
官网的关于online ddl/offline ddl 文档这里描述没写清楚,由此建议所有应用生产的操作,务必先在测试环境验证!
其他
如何判断 DDL 操作为在线操作(Online DDL)
在 OceanBase 数据库中,DDL 操作的在线与离线状态对于业务运行的影响非常重要。本文将介绍如何判断 DDL 操作是否为 Online DDL,以及提供具体的操作步骤和注意事项。有些如列类型变更或混合 DDL 操作在执行前不确定是否为 Online DDL,建议先通过下述方式进行验证判断。
判断 DDL 为在线操作的方式
对于部分操作包含的范围比较广,并不能完全列举 DDL 操作为在线还是离线,建议用户如在有混合 DDL 操作的情况下,明确该操作是否为在线操作。
离线 DDL 的原理 :
OceanBase 的离线 DDL 操作采用 “重建表” 的方式。具体而言,离线 DDL 会新建一张临时的隐藏表(对用户不可见),然后将原表的数据迁移到新建的表中。完成数据迁移后,临时表会被重命名为原表的名称,并且旧表将被删除。因此,离线 DDL 操作完成后,table_id 会发生变化,需要注意在 DDL 执行期间不允许 DML 操作。
借助这一原理,可以判断某个 DDL 操作是否为在线 DDL。
判断方式 :
在 DDL 操作前后执行如下 SQL 语句查看 table_id 是否发生变化,如果没有变化,说明是 Online DDL,如果发生变化,则是 Offline DDL。
select distinct(table_id) from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name='xxx';
判断步骤 :
通过下述判断步骤,判断 DDL 操作是否为 Online DDL。
- 创建一个用以验证的空表:
CREATE TABLE t10(a INT, b INT);
- 查看当前
table_id:
SELECT distinct(table_id)
FROM oceanbase.DBA_OB_TABLE_LOCATIONS
WHERE table_name='t10';
- 执行预期的 DDL 操作:
ALTER TABLE t10 ADD c INT, ADD CONSTRAINT c_idx UNIQUE(c);
- 再次查看
table_id:
SELECT distinct(table_id)
FROM oceanbase.DBA_OB_TABLE_LOCATIONS
WHERE table_name='t10';
- 如果步骤 2 和步骤 4 返回结果
table_id相同,则说明这个 DDL 操作是在线的;如果table_id发生了变化,则对应的 DDL 操作是离线的。



