OceanBase logo

OceanBase

A unified distributed database ready for your transactional, analytical, and AI workloads.

Product Overview
DEPLOY YOUR WAY

OceanBase Cloud

The best way to deploy and scale OceanBase

OceanBase Enterprise

Run and manage OceanBase on your infra

TRY OPEN SOURCE

OceanBase Community Edition

The free, open-source distributed database

OceanBase seekdb

Open source AI native search database

Customer Stories

Real-world success stories from enterprises across diverse industries.

View All
BY USE CASES

Mission-Critical Transactions

Global & Multicloud Application

Elastic Scaling for Peak Traffic

Real-time Analytics

Active Geo-redundancy

Database Consolidation

Resources

Comprehensive knowledge hub for OceanBase.

Blog

Live Demos

Training & Certification

Documentation

Official technical guides, tutorials, API references, and manuals for all OceanBase products.

View All
PRODUCTS

OceanBase Cloud

OceanBase Database

Tools

Connectors and Middleware

QUICK START

OceanBase Cloud

OceanBase Database

BEST PRACTICES

Practical guides for utilizing OceanBase more effectively and conveniently

Company

Learn more about OceanBase – our company, partnerships, and trust and security initiatives.

About OceanBase

Partner

Trust Center

Contact Us

International - English
中国站 - 简体中文
日本 - 日本語
Sign In
Start on Cloud

OceanBase

A unified distributed database ready for your transactional, analytical, and AI workloads.

Product Overview
DEPLOY YOUR WAY

OceanBase Cloud

The best way to deploy and scale OceanBase

OceanBase Enterprise

Run and manage OceanBase on your infra

TRY OPEN SOURCE

OceanBase Community Edition

The free, open-source distributed database

OceanBase seekdb

Open source AI native search database

Customer Stories

Real-world success stories from enterprises across diverse industries.

View All
BY USE CASES

Mission-Critical Transactions

Global & Multicloud Application

Elastic Scaling for Peak Traffic

Real-time Analytics

Active Geo-redundancy

Database Consolidation

Comprehensive knowledge hub for OceanBase.

Blog

Live Demos

Training & Certification

Documentation

Official technical guides, tutorials, API references, and manuals for all OceanBase products.

View All
PRODUCTS
OceanBase CloudOceanBase Database
ToolsConnectors and Middleware
QUICK START
OceanBase CloudOceanBase Database
BEST PRACTICES

Practical guides for utilizing OceanBase more effectively and conveniently

Learn more about OceanBase – our company, partnerships, and trust and security initiatives.

About OceanBase

Partner

Trust Center

Contact Us

Start on Cloud
编组
All Products
    • Databases
    • iconOceanBase Database
    • iconOceanBase Cloud
    • iconOceanBase Tugraph
    • iconInteractive Tutorials
    • iconOceanBase Best Practices
    • Tools
    • iconOceanBase Cloud Platform
    • iconOceanBase Migration Service
    • iconOceanBase Developer Center
    • iconOceanBase Migration Assessment
    • iconOceanBase Admin Tool
    • iconOceanBase Loader and Dumper
    • iconOceanBase Deployer
    • iconKubernetes operator for OceanBase
    • iconOceanBase Diagnostic Tool
    • iconOceanBase Binlog Service
    • Connectors and Middleware
    • iconOceanBase Database Proxy
    • iconEmbedded SQL in C for OceanBase
    • iconOceanBase Call Interface
    • iconOceanBase Connector/C
    • iconOceanBase Connector/J
    • iconOceanBase Connector/ODBC
    • iconOceanBase Connector/NET
icon

OceanBase Database

SQL - V4.2.2

    Download PDF

    OceanBase logo

    The Unified Distributed Database for the AI Era.

    Follow Us
    Products
    OceanBase CloudOceanBase EnterpriseOceanBase Community EditionOceanBase seekdb
    Resources
    DocsBlogLive DemosTraining & CertificationTicket
    Company
    About OceanBaseTrust CenterLegalPartnerContact Us
    Follow Us

    © OceanBase 2026. All rights reserved

    Cloud Service AgreementPrivacy PolicySecurity
    Contact Us
    Document Feedback
    1. Documentation Center
    2. OceanBase Database
    3. SQL
    4. V4.2.2
    iconOceanBase Database
    SQL - V 4.2.2
    Databases
    • OceanBase Database
    • OceanBase Cloud
    • OceanBase Tugraph
    • Interactive Tutorials
    • OceanBase Best Practices
    Tools
    • OceanBase Cloud Platform
    • OceanBase Migration Service
    • OceanBase Developer Center
    • OceanBase Migration Assessment
    • OceanBase Admin Tool
    • OceanBase Loader and Dumper
    • OceanBase Deployer
    • Kubernetes operator for OceanBase
    • OceanBase Diagnostic Tool
    • OceanBase Binlog Service
    Connectors and Middleware
    • OceanBase Database Proxy
    • Embedded SQL in C for OceanBase
    • OceanBase Call Interface
    • OceanBase Connector/C
    • OceanBase Connector/J
    • OceanBase Connector/ODBC
    • OceanBase Connector/NET
    SQL
    KV
    • V 4.6.0
    • V 4.4.2
    • V 4.3.5
    • V 4.3.3
    • V 4.3.1
    • V 4.3.0
    • V 4.2.5
    • V 4.2.2
    • V 4.2.1
    • V 4.2.0
    • V 4.1.0
    • V 4.0.0
    • V 3.1.4 and earlier

    Multi-tenant resource isolation

    Last Updated:2026-04-15 08:27:14  Updated
    Share
    What is on this page
    Advantages of multi-tenant isolation in OceanBase Database
    Isolation from the perspective of user tenants
    Resource classification
    Available CPU resources on an OBServer node
    Available memory resources on an OBServer node
    Check the available resources on each OBServer node
    Resource isolation
    Memory isolation
    CPU isolation
    Metrics and logs

    folded

    Share

    OceanBase Database is a multi-tenant database system. It isolates resources among tenants to prevent resource contention and ensure stable business operation.

    In OceanBase Database, resource units are the basic units for allocating resources to tenants. A resource unit is equivalent to a Docker container. You can create multiple resource units on a node. Each resource unit created on a node occupies a part of the physical resources on the node, such as the CPU and memory resources. The allocation of resources on a node is recorded in an internal table for database administrators.

    You can create multiple resource units across nodes for a tenant. However, a tenant can have only one resource unit on a node. The resource units of a tenant are independent of each other. Currently, OceanBase Database does not aggregate the resource usage of multiple resource units for global resource control.

    Specifically, if the resources on a node fail the demand of a tenant, OceanBase Database does not allow the tenant to compete for resources of other tenants on another node.

    Resource isolation refers to the behavior of controlling resource allocation among multiple resource units on a node, and it is a local behavior of the node. Similar technologies include Docker and virtual machines (VMs), but OceanBase Database does not rely on Docker or VM technologies for resource isolation. It implements resource isolation internally within the database.

    Advantages of multi-tenant isolation in OceanBase Database

    Compared to Docker and VMs, OceanBase Database offers more lightweight tenant isolation and is easier to implement advanced features such as priority management. From the perspective of OceanBase Database requirements, Docker or VMs have the following disadvantages:

    • There are heavy overheads in runtime environments of both Docker and VMs, while OceanBase Database needs to support lightweight tenants.

    • The specification change and migration of Docker or VMs are costly, while OceanBase Database is designed to help tenants change specifications and perform the migration at a faster speed.

    • Tenants cannot share resources such as object pools if Docker or VMs are used.

    • Customizing resource isolation within Docker or VMs, such as priority support within tenants, is challenging.

    In addition, unified views cannot be exposed if Docker or VMs are used.

    Isolation from the perspective of user tenants

    From the perspective of user tenants, the following isolation results are achieved:

    • Memory is completely isolated.

      The details are described as follows:

      • Operators use separate memory during SQL execution. When the memory of a tenant is exhausted, other tenants are not affected.

        For more information about operators used in SQL execution, see User interfaces and query languages.

      • The block cache and MemTable are isolated. When the memory of a tenant is exhausted, the read and write operations of other tenants are not affected.

        For more information about the block cache, see Multi-level caches.

        For more information about the MemTable, see MemTables.

    • CPU resources are isolated based on user-mode scheduling.

      The CPU resources available for a tenant are determined by the unit specification.

      To achieve a better isolation effect, OceanBase Database starts to support the configuration of cgroups to isolate CPU resources in V4.0.0 and later.

    • SQL modules of different tenants do not affect each other.

      The details are described as follows:

      • The SQL plan cache of a tenant is isolated from that of another tenant. When the plan cache of a tenant is evicted, the plan caches of other tenants are not affected.

      • The SQL audit table of a tenant is isolated from that of another tenant. If the queries per second (QPS) value of a tenant is very high, the audit information about other tenants is not flushed.

    • Transaction modules of different tenants do not affect each other.

      The details are described as follows:

      • If the row lock of a tenant is suspended, other tenants are not affected.

      • If the transaction of a tenant is suspended, other tenants are not affected.

      • If the replay for a tenant fails, other tenants are not affected.

    • Clog modules of different tenants do not affect each other.

      The log stream directories are divided by tenant. The structure of a log stream directory on the disk is as follows:

        tenant_id
      ├── unit_id_0
      │   ├── log
      │   └── meta
      ├── unit_id_1
      │   ├── log
      │   └── meta
      └── unit_id_2
          ├── log
          └── meta
      

    Resource classification

    OceanBase Database supports isolation of CPU, memory, and IOPS resources for tenants in V4.0.0 and later. You can specify CPU, memory, IOPS, and log_disk_size resource specifications for each resource unit.

    obclient> CREATE RESOURCE UNIT name
        MAX_CPU = 1, [MIN_CPU = 1,]
        MEMORY_SIZE = '5G',
        [MAX_IOPS = 1024, MIN_IOPS = 1024, IOPS_WEIGHT=0,]
        [LOG_DISK_SIZE = '2G'];
    

    Available CPU resources on an OBServer node

    When an OBServer node starts, the system detects the number of online CPU cores of the physical machine or container. If the detected number of CPU cores is inaccurate, for example, in a containerized environment, you can use the cpu_count parameter to specify CPU resources.

    Each OBServer node reserves two CPU cores for background threads. Therefore, the total CPU cores that can be allocated to tenants are two less than the CPU cores on the OBServer node.

    Available memory resources on an OBServer node

    When an OBServer node starts, the system detects the memory of the physical machine or container. Each OBServer node reserves a part of the memory for other processes. Therefore, the memory size available for the observer process is calculated based on the Physical memory × memory_limit_percentage formula. You can also set the memory_limit parameter to specify the total memory size available for the observer process.

    The memory size for internal shared modules must be subtracted from the memory size available for the observer process. The remaining memory size is available for tenants. The memory size for internal shared modules is specified by the system_memory parameter.

    For more information about memory configurations, see Memory management.

    Check the available resources on each OBServer node

    You can query the oceanbase.GV$OB_SERVERS view to check the available resources on each OBServer node. Here is an example:

    obclient> SELECT * FROM oceanbase.GV$OB_SERVERS\G
    *************************** 1. row ***************************
                     SVR_IP: xx.xx.xx.xx
                   SVR_PORT: 57234
                       ZONE: zone1
                   SQL_PORT: 57235
               CPU_CAPACITY: 14
           CPU_CAPACITY_MAX: 14
               CPU_ASSIGNED: 6.5
           CPU_ASSIGNED_MAX: 6.5
               MEM_CAPACITY: 10737418240
               MEM_ASSIGNED: 6442450944
          LOG_DISK_CAPACITY: 316955164672
          LOG_DISK_ASSIGNED: 15569256438
            LOG_DISK_IN_USE: 939524096
         DATA_DISK_CAPACITY: 10737418240
           DATA_DISK_IN_USE: 624951296
    DATA_DISK_HEALTH_STATUS: NORMAL
    DATA_DISK_ABNORMAL_TIME: NULL
    1 row in set
    

    Resource isolation

    Memory isolation

    OceanBase Database does not support memory over-allocation on OBServer nodes in V4.0.0 and later, because memory over-allocation will cause unstable tenant operation. The MIN_MEMORY and MAX_MEMORY parameters are deprecated, and the MEMORY_SIZE parameter is used instead.

    CPU isolation

    Before OceanBase Database V3.1.x, you can limit the number of threads to control CPU utilization. In OceanBase Database V3.1.x and later, you can configure cgroups to control CPU utilization.

    Thread classification

    Many threads with different features start along with an OBServer node. For more information, see OBServer threads. In this section, threads are classified into the following two types:

    • Threads for processing SQL statements and transaction commits, which are collectively referred to as tenant worker threads.

    • Threads for processing network I/O, disk I/O, compactions, and scheduled tasks, which are referred to as background threads.

    In Oceanbase Database V4.0.0, tenant worker threads and most background threads are tenant-specific, and network threads are shared.

    CPU-based isolation of tenant worker threads based on the number of threads

    CPU resources in a resource unit are isolated based on the number of active tenant worker threads for the resource unit.

    Because the execution of SQL statements may involve I/O waiting and lock waiting, a thread may not fully utilize a physical CPU. Therefore, under default configurations, an OBServer node starts four threads on each CPU. You can set the cpu_quota_concurrency parameter to control the number of threads to be started on a CPU. In this case, if the MAX_CPU parameter of a resource unit is set to 10, 40 parallel active threads are allowed for the resource unit, and the maximum CPU utilization is 400%.

    CPU-based isolation of tenant worker threads based on cgroups

    After cgroups are configured, worker threads of different tenants are stored in different cgroup directories, which improves CPU isolation between tenants. The isolation results are described as follows:

    • If a tenant on an OBServer node has a very high load and the rest of the tenants are relatively idle, then the CPU of the high-load tenant will also be limited by MAX_CPY.

    • If the load of the idle tenants increases, physical CPU resources become insufficient. In this case, cgroups allocate time slices based on weights.

    CPU-based isolation of background threads

    • In OceanBase Database V4.0.0, threads used by a tenant are isolated from those used by another tenant, and each tenant controls a corresponding number of threads.

    • For better isolation, background threads are also allocated to different cgroup directories to achieve isolation between tenants and between tenants and worker threads.

    Large query processing

    Compared with quick response to large queries, quick response to small queries is of higher significance. This means that large queries have lower priorities than small queries. When large queries and small queries contend for CPU resources, the system limits the amount of CPU resources occupied by large queries.

    If a worker thread takes a long time to execute an SQL query, the query is identified as a large query, and the worker thread waits in a Pthread condition to release its CPU resources to other tenant worker threads.

    To support this feature, OBServer nodes insert many checkpoints into the code, making tenant worker threads periodically check their status during the running process. When an OBServer node determines that a worker thread should be suspended, the worker thread waits in a Pthread condition.

    If both large queries and small queries exist, the large queries can occupy at most 30% of the tenant worker threads. The percentage 30% is specified by the large_query_worker_percentage parameter.

    Take note of the following items:

    • If no small queries exist, large queries can occupy 100% of the tenant worker threads. The percentage 30% takes effect only when both large queries and small queries exist.

    • If a tenant worker thread is suspended because it executes a large query, the system may create a tenant worker thread for compensation. However, the total number of tenant worker threads cannot exceed 10 times the value of the MAX_CPU parameter. The multiple 10 is specified by the workers_per_cpu_quota parameter.

    Identify large queries in advance

    An OBServer node starts a new tenant worker thread after it suspends a large query thread. However, if many large queries are initiated, new threads created on the OBServer node are still used to process large queries, and the number of tenant worker threads soon reaches the upper limit. No threads are available for small queries until all the large queries are processed.

    To resolve this issue, an OBServer node predicts whether an SQL query is large before it is executed by estimating the execution time of the SQL query. Prediction is based on the following assumptions: If the execution plans of two SQL queries are the same, the execution time of the SQL queries is also similar. In this case, you can determine whether an SQL query is large based on the execution time of the latest SQL query with the same execution plan.

    If an SQL query is identified as a large query, it is placed in a large query queue, the tenant worker thread executing the query is released, and the system continues to respond to subsequent requests.

    Metrics and logs

    You can search logs by the keyword dump tenant info to view tenant information, such as resource specifications, threads, queues, and request statistics. The logs are updated for each tenant every 30s.

    A sample log is as follows:

    grep 'dump tenant info.tenant={id:1002' log/observer.log | sed 's/,/,\n/g'
    
    [2022-07-20 14:55:40.774143] INFO  [SERVER.OMT] run1 (ob_multi_tenant.cpp:1993) [80700][MultiTenant][T0][Y0-0000000000000000-0-0] [lt=621]
    dump tenant info(tenant={id:1002, // The ID of the tenant.
    tenant_meta:{unit:{tenant_id:1002, // The tenant metadata, including the resource unit configuration, superblock, and creation status of the tenant.
    unit_id:1001, // The ID of the resource unit.
    has_memstore:true, // Indicates whether a MemTable is available.
    unit_status:"NORMAL", // The status of the resource unit. Valid values: UNIT_NORMAL, UNIT_MIGRATE_IN, UNIT_MIGRATE_OUT, UNIT_MARK_DELETING, UNIT_WAIT_GC_IN_OBSERVER, UNIT_DELETING_IN_OBSERVER, andUNIT_ERROR_STAT.
    config:{unit_config_id:1003, // The ID of the resource unit configuration.
    name:"2c2g", // The name of the resource unit configuration.
    resource:{min_cpu:2, // The minimum number of CPU cores in the resource unit configuration.
    max_cpu:2, // The maximum number of CPU cores in the resource unit configuration.
    memory_size:"1.5GB", // The memory size in the resource unit configuration.
    log_disk_size:"5.4GB", // The log disk size in the resource unit configuration.
    min_iops:20000, // The minimum disk IOPS in the resource unit configuration.
    max_iops:20000, // The maximum disk IOPS in the resource unit configuration.
    iops_weight:2}}, // The IOPS weight in the resource unit configuration.
    mode:1, // The compatibility mode. Valid values: 0:MYSQL. 1:ORACLE.
    create_timestamp:1658298418435426, // The time when the resource unit was created.
    is_removed:false}, // Indicates whether the resource unit is marked as deleted.
    super_block:{tenant_id:1002, // The superblock of the tenant.
    replay_start_point:ObLogCursor{file_id=1, // The slog replay point of the tenant.
    log_id=440,
    offset=343322},
    ls_meta_entry:[140](ver=0, // The entry point of the linked table that stores slog checkpoints of the log stream metadata of the tenant.
    mode=0,
    seq=139),
    tablet_meta_entry:[141](ver=0, // The slog checkpoint entry of the tablet metadata of the tenant.
    mode=0,
    seq=140)},
    create_status:1}, // The creation status of the tenant. Valid values: 0: CREATING; 1: CREATE_COMMIT; 2: CREATE_ABORT; 3: DELETING; 4: DELETE_COMMIT.
    unit_min_cpu:"2.000000000000000000e+00", // The minimum number of CPU cores guaranteed.
    unit_max_cpu:"2.000000000000000000e+00", // The maximum number of CPU cores allowed.
    slice:"0.000000000000000000e+00",
    slice_remain:"0.000000000000000000e+00",
    token_cnt:8, // The number of tokens allocated by the scheduler. Each token is converted into a worker thread.
    sug_token_cnt:8,
    ass_token_cnt:8, // The number of tokens allocated to the tenant. You can determine the number of tokens based on the token_cnt field. Typically, the values of the two fields are the same.
    lq_tokens:2, // The number of tokens for large requests. The value of this field is equal to the value of the token_cnt field multiplied by the proportion of large requests.
    used_lq_tokens:0, // The number of worker threads that hold large query tokens.
    stopped:false, // Indicates whether resource units of the tenant are being deleted.
    idle_us:6076629, // The total idle time of the worker threads in one round (10s). The idle time includes only the wait time in queues.
    recv_hp_rpc_cnt:1, // The cumulative number of RPC requests received by the tenant at different levels, including hp(High), np(Normal), and lp(Low).
    recv_np_rpc_cnt:5,
    recv_lp_rpc_cnt:0,
    recv_mysql_cnt:24, // The cumulative number of MySQL requests received by the tenant.
    recv_task_cnt:1, // The cumulative number of internal tasks received by the tenant.
    recv_large_req_cnt:0, // The cumulative number of large requests predicted by the tenant. The value of this field is only incremented but not cleared. The value is incremented upon a retry.
    tt_large_quries:0, // The cumulative number of large requests processed by the tenant. The value of this field is only incremented but not cleared. The value is incremented upon a check.
    pop_normal_cnt:1024555,
    actives:8, // The number of active worker threads. The value is equal to the number of active worker threads of the tenant plus the number of threads suspended due to large queries, which is often equal to the value of the workers parameter. The difference between the values of the actives and workers parameters is the number of inactive threads of the tenant that are waiting to be collected with a delay.
    workers:8, // The number of worker threads held by the tenant, which is equal to the sum of the number of active worker threads of the tenant, the number of threads suspended due to large queries, and the number of inactive threads of the tenant that are waiting to be collected with a delay.
    nesting workers:7, // The number of dedicated threads held by the tenant for nested requests. A total of seven threads correspond to seven nesting levels.
    lq waiting workers:0, // The number of worker threads intended for processing large queries and waiting to be scheduled.
    req_queue:total_size=0 queue[0]=0 queue[1]=0 queue[2]=0 queue[3]=0 queue[4]=0 queue[5]=0 , // The worker queues with different priorities. A smaller value indicates a higher priority.
    large queued:0, // The number of large requests predicted by the tenant.
    multi_level_queue:total_size=0 queue[0]=0 queue[1]=0 queue[2]=0 queue[3]=0 queue[4]=0 queue[5]=0 queue[6]=0 queue[7]=0 , // The worker queues to accommodate nested requests. The values 1 to 7 correspond to the seven nesting levels. queue[0] is invalid. queue[5] accommodates inner SQL requests.
    recv_level_rpc_cnt:cnt[0]=0 cnt[1]=0 cnt[2]=0 cnt[3]=0 cnt[4]=0 cnt[5]=0 cnt[6]=0 cnt[7]=0 ,
    group_map:group_id = 1, // The threads of the group that corresponds to each group_id in the group_map and their queuing status.
    queue_size = 0, // The queuing status of the group queue.
    recv_req_cnt=13526, // The cumulative number of requests in the group that are pushed to the queue.
    pop_req_cnt=13526, // The cumulative number of requests popped out by threads in the group.
    token_cnt = 2, // The number of tokens allocated to the group. Each token is converted into a worker thread.
    min_token_cnt = 2,
    max_token_cnt = 2,
    ass_token_cnt = 2 , // The number of tokens allocated to the group. You can determine the number of tokens based on the token_cnt field. Typically, the values of the two fields are the same.
    rpc_stat_info: pcode=0x150a:cnt=1489 pcode=0x150b:cnt=1091}) // The RPC pcodes that have been received most frequently by the tenant in a period of time. The statistical period is 10 seconds, and the top five RPC pcodes are printed.
    

    Previous topic

    Tenant resource management
    Last

    Next topic

    Resource unit balancing
    Next
    What is on this page
    Advantages of multi-tenant isolation in OceanBase Database
    Isolation from the perspective of user tenants
    Resource classification
    Available CPU resources on an OBServer node
    Available memory resources on an OBServer node
    Check the available resources on each OBServer node
    Resource isolation
    Memory isolation
    CPU isolation
    Metrics and logs