背景
最近,遇到一些HANA Cloud非常复杂的使用场景。
首先,它是一个Multi-tenant即多租户场景,HANA Cloud目前是天然支持的,几乎不需要什么配置,直接可以初始化,但是要将你的Service App做成PaaS或者SaaS,则还需要一些配接性的工作。
其次,这些目标Tenant不是一般的tenant,它要求里边的数据完全能被客户加密控制,客户随时都能更换加密的key。而且各个客户相互独立。要知道这些Tenant DB都位于Hana Cloud Database的集中控制下,还能彼此保持相互独立。最后就是你弄你的,我弄我的,相互不干扰。这个确实有些太过于强大。
作为对比联想,如果是在PostgreSQL当中实现这样的功能,如果是基于Database的、schema的,则实现方案会完全不同。尤其是Tenant用户能自己控制自己(database)的key, 这应该需要与安全控制系统进行集成才能比较好的完成。
最后,就是比较恼人的清理工作。有一天,customer想清除掉已建的tenant database, 这个过程,正常情况下需要自动完成,可是有时候自动完成不了,就需要手动清理,而且还不能影响系统的其它Tenant DB (instance)。
分析与实作
我在前边也曾经零碎的写过一些,使用相关的HANA存储过程或函数的脚本来清掉对应的schema,然后对应的HDI instance (Tenant DB)也就大概率被干掉了。
如,我们可以使用下面的脚本(假定我们是dbadmin用户):
1-- 先授权
2CREATE LOCAL TEMPORARY COLUMN TABLE #PRIVILEGES LIKE _SYS_DI.TT_API_PRIVILEGES;
3INSERT INTO #PRIVILEGES (PRINCIPAL_NAME, PRIVILEGE_NAME, OBJECT_NAME) SELECT 'DBADMIN', PRIVILEGE_NAME, OBJECT_NAME FROM _SYS_DI.T_DEFAULT_CONTAINER_GROUP_ADMIN_PRIVILEGES;
4
5CALL _SYS_DI.GRANT_CONTAINER_GROUP_API_PRIVILEGES('BROKER_CG', #PRIVILEGES, _SYS_DI.T_NO_PARAMETERS, ?, ?, ?);
6
7DROP TABLE #PRIVILEGES;
8
9-- 调用DROP_CONTAINER
10CREATE LOCAL TEMPORARY COLUMN TABLE #DROP_CONTAINER_PARAMETERS LIKE _SYS_DI.TT_PARAMETERS;
11INSERT INTO #DROP_CONTAINER_PARAMETERS ( KEY, VALUE ) VALUES ( 'ignore_work', 'true' );
12INSERT INTO #DROP_CONTAINER_PARAMETERS ( KEY, VALUE ) VALUES ( 'ignore_deployed', 'true' );
13INSERT INTO #DROP_CONTAINER_PARAMETERS ( KEY, VALUE ) VALUES ( 'ignore_errors', 'true' );
14CALL _SYS_DI#BROKER_CG.DROP_CONTAINER('{TENANT_SCHEMA}', #DROP_CONTAINER_PARAMETERS, ?, ?, ?);
15DROP TABLE #DROP_CONTAINER_PARAMETERS;
我们通过调用:_SYS_DI#BROKER_CG.DROP_CONTAINER,就可以基本上删除对应的container。
这里头术语有些混乱,对于Tenant DB,有叫CONTAINER的,有叫HDI instance的。这三个指的基本上是同一个东西。传入TENANT_SCHEMA,大概率也能删掉这个SCHEMA对应的CONTAINER。
实际上它会删掉{TENANT_SCHEMA}, {TENANT_SCHEMA}_#OO, {TENANT_SCHEMA}_#DI, {TENANT_SCHEMA}_{GUID}_RT, {TENANT_SCHEMA}_{GIUD}_DT。
但是有些极端情况,它没办法删干净,比如,它把{TENANT_SCHEMA}_{GIUD}_DT给留下了。
就像下边这样:
如何解决?
依然是调用相关脚本。思路也依然还是,授予相关的权限,执行,然后再收回权限,比如:
1-- 1. login with dbadmin in HANA client
2
3-- 2. grant operator privileges for group: BROKER_UG_HDISHARED
4CALL "SYSTEM"."GRANT_USERGROUP_OPERATOR"('group: BROKER_UG_HDISHARED');
5
6-- 3. Drop the target USER cascade
7DROP USER E20CXXXXXXXXXXXXXXXX86A10156F5_14DXXXXXXXXXXXXXXXXXXSUUZQ_DT CASCADE;
8
9-- 4. 收加权限
10CALL "SYSTEM"."REVOKE_USERGROUP_OPERATOR"('BROKER_UG_HDISHARED');
这4步看似简单,但是要想找到对应的权限,再执行,还是挺费劲的。
HANA里头内置的GROUP, ROLE实在太多了。记不住,暂且把那些大的常用的一些ROLE以及相关的方法调用收集下来。
在功能上,因为是针对不同的tenant, HANA能做到某一个TENANT,进行特定的数据恢复到过去的某一个时间点上。相当于做到Database/Schema level上的PITR。基本上就是为了Multi-Tenant量身定做的。
以上这些调用或操作,实际上已经封装到HANA Cloud的相关microservice的API调用里头,只是在某些极端情况会出现清理失败的情况,这个时候就需要自己执行脚本进行手动清理,确保没有垃圾资源在系统中驻留。
两块脚本一配合,基本上你想清除的都能给你清的干干净净。