ITPub博客

首页 > 数据库 > 国内数据库 > OceanBase 源码解读(五):租户的一生

OceanBase 源码解读(五):租户的一生

原创 国内数据库 作者:OceanBase数据库 时间:2021-11-10 16:58:21 0 删除 编辑
此前,带你读源码第四篇 《 戳这里回顾 : OceanBase 源码解读(四):事务的一生 》为大家介绍了事务的外部接口相关知识。本文将介绍社区版中创建、删除租户、资源隔离的相关代码。


OceanBase 数据库是支持多租户的,这里租户的概念类似于传统数据库的数据库实例。租户下可以建立数据库,在租户的数据库下可以建立表。

多租户特性可以降低资源使用和维护成本。每个租户可以被赋于一定的资源(比如 CPU、内存)。OceanBase集群初始内置了一个系统租户 sys,可以用来管理OceanBase 集群。 租户的资源是分配在资源池上的,通过资源配置和设定资源池可以实现对租户资源的控制。
 
在创建租户之前,需要至少一个空闲的资源池;创建资源池需要先定义每个单元的规格。
 
我们称一个资源单元为 UNIT,UNIT是最小的资源分割单位。一个资源池中包含若干 UNIT,一台Observer 只能有一个资源池的一个 UNIT。一个资源池只能赋予给一个租户,一个租户可以包含多个资源池。
 
略过 SQL 的解析和处理,这部分的主体代码都是在 rootserver 目录下。
 
大概涉及到以下接口:


create resource unit

SQL参考:
    CREATE RESOURCE UNIT unitname MAX_CPU [=] cpunum, MAX_MEMORY [=] memsize, MAX_IOPS [=] iopsnum, MAX_DISK_SIZE [=] disksize, MAX_SESSION_NUM [=] sessionnum, [MIN_CPU [=] cpunum,][MIN_MEMORY [=] memsize,] [MIN_IOPS [=] iopsnum] ;
     
    这部分代码比较简单,创建一个 UNIT 规格,就是把这个规格记录在内部表(__all_unit_config)。在没有任何资源池引用这个规格时,它并没有什么用,可以随意的修改或者删除。
     
    代码上可以从这个接口去阅读:

    int ObRootService::create_resource_unit(const obrpc::ObCreateResourceUnitArg& arg)


    create resource pool

    SQL参考:
      CREATE RESOURCE POOL poolname UNIT [=] unitname, UNIT_NUM [=] unitnum, ZONE_LIST [=] (‘zone’ [, ‘zone’ …]);
       
      创建资源池需要定义这个资源池引用的规格,这个资源处分布在哪几个 zone,每个 zone 存在几个 UNIT,这里的重点是要在哪些 server 上把这部分 UNIT 分配出来。

      可以从这个接口去阅读:

      int ObRootService::create_resource_pool(const obrpc::ObCreateResourcePoolArg& arg)

       
      这里涉及到的内部表有:
      __all_resource_pool、__all_unit。
       
      具体如何分配 UNIT 可以参考这个接口:

      int ObUnitManager::allocate_pool_units(ObISQLClient& client, const share::ObResourcePool& pool)


      create tenant
       
      SQL参考:
        CREATE TENANT [IF NOT EXISTS] tenantname      [tenant_characteristic_list] [opt_set_sys_var]tenant_characteristic_list: tenant_characteristic [, tenant_characteristic...]tenant_characteristic: COMMENT 'string'  |{CHARACTER SET | CHARSET} [=] charsetname |COLLATE [=]  collationname|REPLICA_NUM [=] num |ZONE_LIST [=] (zone [, zone…]) |PRIMARY_ZONE [=] zone  |DEFAULT TABLEGROUP [=] {NULL | tablegroup}|RESOURCE_POOL_LIST [=](poolname [, poolname…])|LOGONLY_REPLICA_NUM [=] num|LOCALITY [=] 'locality description'opt_set_sys_var:{ SET | SET VARIABLES | VARIABLES } system_var_name = expr [,system_var_name = expr] ...
         
        资源池创建成功后,就可以引用这个资源池创建租户。创建租户分为三个事务,为什么要分为三个事务呢?我们可以带着这个问题从这个接口开始阅读代码

        int ObRootService::create_tenant(const ObCreateTenantArg& arg, UInt64& tenant_id)


        三个事务可以从这个接口阅读:

        int ObDDLService::create_tenant_env(share::schema::ObSchemaGetterGuard& schema_guard, const obrpc::ObCreateTenantArg& arg,
             const common::ObRegion& region, share::schema::ObTenantSchema& tenant_schema, const int64_t frozen_version,
             const common::ObString* ddl_stmt_str = NULL);

         
        事务一

        确定租户使用的资源池,并把这些资源池都赋予给这个租户。构建了ObTenanSchema,包括租户的 locality,primary_zone等信息。创建这个租户的系统表的 Partition;
         
        事务二

        这个事务是构建了租户内部的数据,例如系统表的元信息,内部用户,database 等。大概包括以下内容:


        这个事务结束后,实际上租户已经创建完成,可以正常使用。
         
        事务三
         
        这个事务就是修改了租户的创建,从CREATING到NORMAL。给出一个创建租户结束的标记。
         
        为什么创建租户需要三个事务?因为事务不能跨租户。
         
        drop tenant

        SQL参考:
          DROP TENANT [IF EXISTS] tenant_name [FORCE];
           
          删除租户实际上只删除了租户的ObTenanSchema。租户删除了,租户引用的资源池还是存在的

          int ObRootService::drop_tenant(const ObDropTenantArg& arg)

           
          drop resource pool
           
          SQL参考:
            DROP RESOURCE POOL poolname;
             
            只有没有租户引用的资源池才可以被删除

            int ObRootService::drop_resource_pool(const obrpc::ObDropResourcePoolArg& arg)


            drop resource unit
             
            SQL参考:
              DROP RESOURCE UNIT unitname;
               
              只有没有资源池引用的规格才可以被删除,只涉及到内部表的修改,接口如下

              int ObRootService::drop_resource_unit(const obrpc::ObDropResourceUnitArg& arg)


              租户隔离
               
              租户的资源是互相隔离的,CPU 隔离和调度的代码位于 src/observer/omt。

               
              所有 OceanBase 的一级数据库对象,如表,索引,database/schema,用户等,在系统表和内存中都是用一个 uint64 作为 ID 标识的。为了实现方便,很多时候,在内存中这些 ID 里编码了租户 ID,前 24bit是租户ID。


              来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69909943/viewspace-2841567/ ,如需转载,请注明出处,否则将追究法律责任。

              请登录后发表评论 登录
              全部评论
              欢迎来 OceanBase 开源官网技术切磋 https://open.oceanbase.com/answer

              注册时间:2019-02-13

              • 博文量
                580
              • 访问量
                585185