问题背景
某核心资源系统业务2021年迁移到国产数据库OceanBase最早使用的版本是OceanBase 2.2.76,因OceanBase次版本不支持split partition功能只能顺序的add分区,每次添加拆分分区操作都是先删除max分区然后add partition,在把max分区也add上,但是这种添加分区的方式不适合复合分区的情况,列入region+时间的复合RANGE分区,分区里有多个部分地市的max分区。
这样就不能通过删除中间的max分区在add分区了,为此在迁移前oracle库提前拆到2022年全年的分区,迁移到ob库不用在处理分区,现在到了22年年底需要添加新的分区保障业务正常运行,OceanBase开发了新版本支持复合分区的add分区功能,此版本包括OceanBase 2.2.77(OceanBase 2.0的最终版本)和OceanBase 3.2.3.2,在新版本的测试环境测试验证分区的add功能。测试步骤如下,希望能有参考意义。
解释:
分区技术(Partitioning)是 OceanBase 非常重要的分布式能力之一,它能解决大表的容量问题和高并发访问时的性能问题,主要思想就是将大表拆分为更多更小的结构相同的独立对象,即分区。普通的表只有一个分区,可以看作分区表的特例。每个分区只能存在于一个节点内部,分区表的不同分区可以分散在不同节点上。
测试过程
步骤1:第一步系统租户root用户下检查参数是否打开,和max分区是否有数据
用ROOT租户进入查看 _enable_add_between_range_partitions参数,默认状态为FALSE,使用如下语句:
select b.tenant_name,a.* from
__all_virtual_tenant_parameter_info a,__all_tenant b where
name = '_enable_add_between_range_partitions' and
b.tenant_id > 1000 and a.tenant_id=b.tenant_id order by
1,zone;,复制
结果如下图:
步骤2:修改 _enable_add_between_range_partitions 为 TRUE
同样也是在root租户下执行。
执行命令:
alter system set _enable_add_between_range_partitions = 'True' tenant='obzy02';
复制
注意事项:
tenant为上面查询的结果,根据需要修改;处理完毕后将参数修改回 False。
执行如图:
obclient[root]>alter system set
_enable_add_between_range_partitions = 'True'
tenant='obzy02';
Query OK, 0 rows affected (0.01 sec)复制
步骤3:再次查询参数值,确认已经修改成功
同样也是在root租户下执行。
执行命令:
select * from __all_virtual_tenant_parameter_info where name
= '_enable_add_between_range_partitions' and tenant_id >
1001;复制
或是步骤1里的语句,当结果data_type字段改为true说明功能启用可以add复合分区,可以执行add 分区命令验证add分区。
结果如下图:
步骤4:验证max分区是否有数据
因add分区的功能当max分区有数据时,可能会造成数据的迁移(数据可能会保留在max分区,没有迁移到拆除的分区,这个需要验证,测试发现数据到了新加的分区上符合期望的情况)和全局索引的失效。
在root 租户验证max分区是否有数据,这个语句不完全准确,部分max分区没有查询到,需要手工统计或是ob优化下视图便于按分区名查询(在root租户只能查到分区的id不能查到分区的名称)。
查询语句:
SELECT /*+READ_CONSISTENCY(WEAK),query_tzyeout(100000000)*/
c.tenant_name,
d.database_name,
b.table_name,
a.partition_id,
a.row_count,
round(a.required_size 1024 / 1024 / 1024, 2) table_size_GB
from
(select tenant_id,table_id,max(partition_id) partition_id from __all_virtual_meta_table group by tenant_id,table_id) m,
__all_virtual_meta_table a,
__all_virtual_table b,
__all_tenant c,
__all_virtual_database d
WHERE a.ROLE = 1
AND instr(a.member_list, a.svr_ip) > 0
and m.tenant_id=a.tenant_id
and m.table_id=a.table_id
and m.partition_id=a.partition_id
AND a.tenant_id = b.tenant_id
AND a.table_id = b.table_id
AND b.tenant_id = c.tenant_id
AND b.database_id = d.database_id
and m.partition_id>17
and d.database_name not in('PRO_MUSER')
and b.table_name in(
'CS_ZYEI_CUR',
'CS_REC_ECASHLOAN_LOG',
'ZY_ASYN_TASK',
'ZY_ASYN_TASKHIS',
'ZY_ASYN_TASK_BLOCK',
'ZY_ASYN_TASK_BLOCKHIS',
'ZY_ASYN_TASK_LOCK',
'ZY_ASYN_TASK_PARAMTER')
ORDER BY c.tenant_name, b.table_name, partition_id;复制
查询结果:
步骤5:执行add分区命令
此操作在业务租户的业务用户,或是业务租户的sys用户下执行。
验证按月分区,按地市+月份分区类型的表,步骤如下:
1)验证按月分区的表
obclient[SYS]>select t.table_owner,t.table_name,t.partition_name from dba_tab_partitions t where t.table_name='ZY_IF_CTRM_ORDER_HIS';
+-------------+-----------------------+----------------+
| TABLE_OWNER | TABLE_NAME | PARTITION_NAME |
+-------------+-----------------------+----------------+
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202201 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202202 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202203 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202204 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202205 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202206 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202207 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202208 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202209 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202210 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202211 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202212 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_MAX |
+-------------+-----------------------+----------------+
13 rows in set (0.87 sec)
obclient[SYS]>复制
2)验证max分区是否有数据
select count(1) from ZY.ZY_IF_CTRM_ORDER_HIS partition (P_MAX);
obclient[SYS]>select count(1) from ZY.ZY_IF_CTRM_ORDER_HIS partition (P_MAX);
+----------+
| COUNT(1) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)复制
3)执行分区添加语句
alter table ZY.ZY_IF_CTRM_ORDER_HIS add partition P_202301
values less than (TO_DATE('202302', 'YYYYMM',
'NLS_CALENDAR=GREGORIAN')) ;
obclient[SYS]>alter table ZY.ZY_IF_CTRM_ORDER_HIS add
partition P_202301 values less than (TO_DATE('202302',
'YYYYMM', 'NLS_CALENDAR=GREGORIAN')) ;
Query OK, 0 rows affected (0.20 sec)复制
4)通过语句验证添加的分区
obclient[SYS]>select t.table_owner,t.table_name,t.partition_name from dba_tab_partitions t where t.table_name='ZY_IF_CTRM_ORDER_HIS';
+-------------+-----------------------+----------------+
| TABLE_OWNER | TABLE_NAME | PARTITION_NAME |
+-------------+-----------------------+----------------+
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202201 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202202 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202203 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202204 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202205 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202206 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202207 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202208 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202209 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202210 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202211 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202212 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_202301 |
| ZY | ZY_IF_CTRM_ORDER_HIS | P_MAX |
+-------------+-----------------------+----------------+
14 rows in set (0.82 sec)
obclient[SYS]>复制
步骤6:在操作完检查失效的索引
此步业务用户下检查,此命令可以查出失效索引和创建索引的的ddl命令,因为ob暂时不支持失效索引的rebuild命了,索引失效了只能drop了重建。索引检查失效索引并重建这一步是非常重要的检查步骤。
使用命令:
select /*+ rule */t.owner,t.table_name,'drop index '||t.owner||'.'||t.index_name||';','select
dbms_metadata.get_ddl('||'''INDEX'''||','''||T.INDEX_NAME||''','||''''||T.OWNER||''') FROM DUAL UNION ALL'
FROM Dba_Indexes t WHERE t.status ='UNUSABLE';复制
步骤7:在所有分区操作完后将参数关闭
此命令在root租户下执行,验证语句同步骤1:
alter system set _enable_add_between_range_partitions = 'False' tenant='obzy02';
复制
至此ob库分区添加共用验证完。
结语:
1)此次分区add功能只是通过add partition命令实现了类似split partition的功能,完善了符合分区不能add分区的情况,但是还不能支持split partition 功能,希望后期支持。
2)Ob的失效索引不支持rebuild命令,这个导致索引失效后操作较复杂,既增加了操作时间(不能编译分区失效索引),又增加了操作难度(获取建索引语句,并删除索引重建难免有遗漏的可能带来了sql效率降低的风险),建议后期增加此功能。
oceanbase处于发展阶段,部分功能还不完善,希望后期越做越好。

本文作者:王宏明(上海新炬中北团队)
本文来源:“IT那活儿”公众号
