OceanBase 原始碼解讀(五):租戶的一生

OceanBase資料庫發表於2021-11-10
此前,帶你讀原始碼第四篇 戳這裡回顧 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部落格 ” ,連結:http://blog.itpub.net/69909943/viewspace-2841567/,如需轉載,請註明出處,否則將追究法律責任。

              相關文章