一、observer内存限制;
1、 OBServer 可用的总内存大小限制:
memory_limit 的默认值为 0。如果该值不为 0,则系统会忽略 memory_limit_percentage 的设置而优先使用 memory_limit 配置的值。例如,一台物理机的内存为 100 GB, memory_limit_percentage 设置为 80,表示使用 80% 的内存,而 memory_limit 参数设置为 '90G',则实际物理机上 OceanBase 数据库可分配的内存使用 memory_limit 的配置,即 90 GB。 memory_limit 的默认单位为 MB。例如, memory_limit='40G' 表示设置 OceanBase 数据库进程的使用内存上限是 40 GB。由于默认单位为 MB,则 memory_limit=40960 与 memory_limit='40G' 设置的值相同。 memory_limit 的值目前无上限。
如果设置的内存最大上限超过了实际的物理内存总和,则会导致系统中其他按总内存计算的值偏大。
如果希望限制运行中的 OceanBase 数据库的内存大小,可以直接修改 memory_limit 的值,使其达到预期。设置后,后台参数 Reload 线程会使其动态生效,无需重启。但是在设置时,需要保证 memory_limit 的值小于系统总的值 memory_limit 的值必须大于 OBServer 节点实际已使用的内存;2、查看OBServer节点的总内存参数配置:
show parameters like 'memory_limit'; select * from oceanbase.GV$OB_PARAMETERS where NAME='memory_limit';3、查看OBserver节点使用内存情况:
方式1:如下查看某个observer节点,hold:总的已分配的内存,used表示已经使用的内存;
root@ : oceanbase 20:16:34>select SVR_IP,SVR_PORt ,/* MONITOR_AGENT */ sum(hold)/1024/1024/1024 as hold, sum(used)/1024/1024/1024 as used from gV$OB_MEMORY group by SVR_IP,SVR_PORT;
+--------------+----------+-----------------+-----------------+
| SVR_IP | SVR_PORt | hold | used |
+--------------+----------+-----------------+-----------------+
| 10..143 | 2882 | 23.881857663393 | 8.934884364716 |
| 10..142 | 2882 | 24.999297976493 | 10.238973292521 |
| 10..141 | 2882 | 31.904126092791 | 10.675031124613 |
+--------------+----------+-----------------+-----------------+
3 rows in set (0.012 sec)
方式2:如下查看某个observer总的内存使用量(约等于top显示的进程的内存大小);
root@ : oceanbase 20:17:13>SELECT SVR_IP,SVR_PORT ,sum(VALUE)/1024/1024/1024 FROM gv$sysstat WHERE NAME='observer memory used size' group by SVR_IP,SVR_PORT;
+--------------+----------+---------------------------+
| SVR_IP | SVR_PORT | sum(VALUE)/1024/1024/1024 |
+--------------+----------+---------------------------+
| 10..143 | 2882 | 25.265148162842 |
| 10..142 | 2882 | 26.555618286133 |
| 10..141 | 2882 | 34.181869506836 |
+--------------+----------+---------------------------+
3 rows in set (0.045 sec)
4、修改OBserver节点内存限制:
ALTER SYSTEM SET memory_limit='32G';OBServer 上 memory_limit 设置生效需要同时满足两个条件: 1)500 租户的预留内存需要不小于实际占用内存。 2)memory_limit 取值需高于 system_memory 和 Unit 已分配内存之和。在不满足以上限制条件时,设置 memory_limit 不会报错,也不生效二、租户的内存限制:
OceanBase 数据库是多租户设计的数据库,同一个进程会运行着多个租户的请求,从租户资源划分上可以分为三类,500 租户内存、系统租户内存、业务租户内存。- 500 是个特殊的虚拟租户,共享性的、非实体租户消耗的内存都被 OceanBase 数据库划归 500 租户。
- 系统租户是 OceanBase 数据库自动创建的第一个实体租户,管理着集群相关的内部表,这些内部表上的请求触发的内存就划归到了 sys 租户。
- 业务租户就是集群安装后由 DBA 创建的跑业务流量的实体租户,这些租户的请求触发的内存就划归租户自己。
1、500租户:
1)500租户预留的内存容量
system_memory:用于设置系统预留给租户 ID 为 500 的租户的内存容量,系统预留内存不能分配给普通租户使用。默认值为0M,表示系统会自动根据当前系统的内存情况来调整内存使用策略。2)修改方式
ALTER SYSTEM SET system_memory='30G';注意它不是 limit 的语义,目前的实现上 500 租户实际可使用内存是可能突破 system_memory 的,但其他租户可使用内存不能超过 memory_limit - system_memory 的值。3)查看500租户的内存使用情况
select svr_ip,svr_port , /* MONITOR_AGENT */ sum(hold)/1024/1024/1024 as hold,sum(used)/1024/1024/1024 as used from gV$OB_MEMORY where tenant_id = 500 and MOD_NAME <> 'KvstorCacheMb' group by svr_ip,svr_port;2、系统租户
系统租户是 OceanBase 数据库的集群管理员为安装 OceanBase 数据库时自动创建。V4.2.1 版本前,系统租户实际可使用的内存上限为
sys_unit_config.memory_size。从 V4.2.1 版本开始,系统租户实际可使用的内存上限为:
hidden_sys_memory + sys_unit_config.memory_size。其中:sys_unit_config.memory_size 的值由资源规格
sys_unit_config 中的
memory_size 决定。
sys_unit_config 是系统租户默认的资源规格,其默认的内存资源为最小资源。由于系统租户也是一个正常的租户,故可以通过 ALTER RESOURCE 语句修改 sys_unit_config 中 memory_size 的值。
hidden_sys_memory 的值由隐藏配置项 _hidden_sys_tenant_memory 控制。隐藏配置项 _hidden_sys_tenant_memory 的默认值为 0G,表示系统会按照一定的规则进行自适应分配 hidden_sys_memory 的值。不建议修改隐藏配置项 _hidden_sys_tenant_memory 的值。
1)查看sys_unit_config.memory_size的大小:
root@10.1.150 : oceanbase 00:32:45>select a.TENANT_NAME,a.TENANT_ID ,b.UNIT_GROUP_ID,c.NAME ,c.MEMORY_SIZE/1024/1024/1024 from DBA_OB_TENANTS a, DBA_OB_UNITS b, DBA_OB_UNIT_CONFIGS c where a.TENANT_ID=b.TENANT_ID and b.UNIT_config_ID=c.UNIT_CONFIG_ID and TENANT_NAME='sys';
+-------------+-----------+---------------+-----------------+------------------------------+
| TENANT_NAME | TENANT_ID | UNIT_GROUP_ID | NAME | c.MEMORY_SIZE/1024/1024/1024 |
+-------------+-----------+---------------+-----------------+------------------------------+
| sys | 1 | 1 | sys_unit_config | 5.000000000000 |
| sys | 1 | 1 | sys_unit_config | 5.000000000000 |
| sys | 1 | 1 | sys_unit_config | 5.000000000000 |
+-------------+-----------+---------------+-----------------+------------------------------+
3 rows in set (0.040 sec)
2)查看隐含参数_hidden_sys_tenant_memory
select * from oceanbase.GV$OB_PARAMETERS where NAME='_hidden_sys_tenant_memory'\G alter system set _hidden_sys_tenant_memory='0M'; #修改隐含参数3、查看memory_limit、system_memory、_hidden_sys_tenant_memory实际生效值
方式1:在observer.log文件中查询关键词"update observer memory config"
$grep 'update observer memory config' observer.log [2024-01-03 11:19:26.248812] INFO [SHARE.CONFIG] reload_config (ob_server_config.cpp:361) [54251][observer][T0][Y0-0000000000000000-0-0] [lt=22] update observer memory config success(memory_limit=8589934592, system_memory=1073741824, hidden_sys_memory=1073741824)
方式2:查询视图GV$SYSSTAT
root@10.150 : oceanbase 17:14:17>select * from GV$SYSSTAT where NAME like '%effective%' and CON_ID=1; +--------+--------------+----------+------------+---------------------------------+-------+--------------+------------+---------+ | CON_ID | SVR_IP | SVR_PORT | STATISTIC# | NAME | CLASS | VALUE | VALUE_TYPE | STAT_ID | +--------+--------------+----------+------------+---------------------------------+-------+--------------+------------+---------+ | 1 | 10.1.143 | 2882 | 703 | effective observer memory limit | 64 | 216166137856 | SET_VALUE | 140014 | | 1 | 10.1.143 | 2882 | 704 | effective system memory | 64 | 17293291028 | SET_VALUE | 140015 | | 1 | 10.1.143 | 2882 | 705 | effective hidden sys memory | 64 | 6484984135 | SET_VALUE | 140016 | | 1 | 10.1.141 | 2882 | 703 | effective observer memory limit | 64 | 216166219776 | SET_VALUE | 140014 | | 1 | 10.1.141 | 2882 | 704 | effective system memory | 64 | 17293297582 | SET_VALUE | 140015 | | 1 | 10.1.141 | 2882 | 705 | effective hidden sys memory | 64 | 6484986593 | SET_VALUE | 140016 | | 1 | 10.1.142 | 2882 | 703 | effective observer memory limit | 64 | 216166137856 | SET_VALUE | 140014 | | 1 | 10.1.142 | 2882 | 704 | effective system memory | 64 | 17293291028 | SET_VALUE | 140015 | | 1 | 10.1.142 | 2882 | 705 | effective hidden sys memory | 64 | 6484984135 | SET_VALUE | 140016 |
+--------+--------------+----------+------------+---------------------------------+-------+--------------+------------+---------+
9 rows in set (0.021 sec)
3、用户租户(业务租户)
1)限制租户内存大小
用户租户内存由租户创建 Unit 时其 memory_size 的大小定义的, memory_size 为用户租户的整体内存大小,其内存包含用户租户本身的内存和其对应 Meta 租户的内存。在创建用户租户时,其允许创建的最小内存由隐藏配置项 __min_full_resource_pool_memory 控制,其默认值为 5G,取值范围为 [1073741824,+∞)。2)查看租户内存使用情况
使用 GV$OB_TENANT_MEMORY 视图。此视图提供了各个租户的内存使用总量。以下是查询示例:root@10.1.150 : oceanbase 20:28:44>SELECT svr_ip,svr_port, tenant_id, SUM(hold)/1024/1024/1024 AS HOLD_MEMORY_GB FROM oceanbase.GV$OB_TENANT_MEMORY GROUP BY svr_ip,svr_port, tenant_id;
+--------------+----------+-----------+-----------------+
| svr_ip | svr_port | tenant_id | HOLD_MEMORY_GB |
+--------------+----------+-----------+-----------------+
| 10.1.142 | 2882 | 1 | 4.587486267090 |
| 10.1.142 | 2882 | 500 | 1.689975738525 |
| 10.1.142 | 2882 | 508 | 0.034046173096 |
| 10.1.142 | 2882 | 509 | 0.022327423096 |
| 10.1.142 | 2882 | 1001 | 0.865734100342 |
4、Meta 租户
Meta 租户的内存资源不支持共享,Meta 租户和用户租户的内存资源需要隔离。默认 Meta 租户占整体租户规格的 10%。为了保证 Meta 租户正常运行,Meta 租户内存资源规格最小为 512M,不设最大值。整体租户内存规格减去 Meta 租户内存规格即为用户租户的内存规格。整体租户规格最小值调整为 1G。下面举例说明:- 租户规格大于等于 10G 时,Meta 租户和用户租户内存规格比例为 1:9。
- 租户规格大于等于 2G 时,Meta 租户的内存规格固定为 1G,剩余资源给用户租户。
- 租户规格大于等于 1G 并且小于 2G 时,Meta 租户固定分配 512 M,剩余资源给用户租户。
三、租户内存中管理
https://www.oceanbase.com/docs/enterprise-oceanbase-database-cn-1000000002013285 --内存管理1、租户内存管理总览:
用户租户本身的内存和其对应的 Meta 租户的内存可以分为装载增量数据的 MemStore 以及 KVCache 缓存。 OceanBase 数据库把租户内部的内存总体上分为以下两个部分:- 不可动态伸缩的内存-------MemStore(memtable)
- 可动态伸缩的内存——KVCache
- MemTable:每个分区对应 1 个 MemTable(共 3×100=300 个 MemTable),每个 MemTable 存储该分区的实时写入的增量数据。 MemTable 是 分区级的实时写缓存,直接承接写操作,存储单分区的活跃数据,是 LSM-Tree 顶层结构的核心组件
- MemStore:每个 OBServer 节点有 1 个 MemStore,负责管理这 100 个分区的 MemTable,监控它们的大小并触发刷盘。 MemStore 是 节点级的内存存储管理器,负责管理所有分区的 MemTable,协调资源分配、刷盘调度和内存回收,是内存存储体系的管理者
2、不可动态伸缩的内存管理
1)租户不可伸缩内存介绍
目前与不可动态伸缩内存相关的配置只有 memstore_limit_percentage 和 ob_sql_work_area_percentage,前者表示租户的 MemStore 部分最多占租户总内存上限的百分比,后者表示 SQL 阻塞算子工作区内存占用上限。租户的写入或者更新会增加 MemStore 的内存使用, 当租户的 MemStore 部分内存到达上限以后,后续的写入或者更新操作将会被拒绝。OceanBase 数据库会根据 MemStore 的内存使用比例决定何时进行转储或者合并释放 MemStore 的内存,该比例由配置项 freeze_trigger_percentage 控制,表示当 MemStore 内存占用到达其上限的百分比后就进行冻结(转储的前置动作),默认值为租户 MemStore 内存上限的 20%。2)memstore_limit_percentage参数
设置租户使用 MemStore 的内存占其总可用内存的百分比。其中,租户 MemStore 的内存= min_memory* memstore_limit_percentage。 min_memory 为创建租户时指定的值。3)ob_sql_work_area_percentage参数
指定 SQL 工作区的内存占整个租户内存的百分比。 ob_sql_work_area_percentage 是 SQL 工作区内存参数,表示 SQL 可能耗费大量内存的SQL排序等阻塞性算子所使用的内存。3、可动态伸缩的内存管理
1)缓存介绍
OceanBase 数据库将绝大多数的 KV 格式的缓存统一在了 KVCache 中进行管理,KVCache 支持动态伸缩、不同类型 Cache 的优先级控制以及智能的淘汰机制。可动态伸缩的 KVCache 会尽量使用除去不可动态伸缩后租户的全部内存,当租户内存满时,会优先从 KVCache 中淘汰未被引用的内存来使用。
- BloomFilter Cache
- Row Cache
- Block Index Cache
- Block Cache
- Fuse Row Cache
- Partition Location Cache:用于缓存 Partition 的位置信息,帮助对一个查询进行路由。
- Schema Cache:缓存数据表的元信息,用于执行计划的生成以及后续的查询。
- Clog Cache:缓存 clog 数据,用于加速某些情况下 Paxos 日志的拉取。
2)缓存优先级设置
KVCache 一般不需要配置,特殊场景下可以通过参数控制各种 Cache 的优先级,优先级高的 Cache 比优先级低的 Cache 更容易被保留在 Cache 中。用于控制不同类型 Cache 的优先级的参数如下表所示。参数值越大表示优先级越高。3)租户缓存使用情况
缓存命中率查询缓存的大小:OceanBase V4.0 及以上版本可以使用GV$OB_KVCACHE或者gv$sysstat来查询!
查看block_cache的大小:每个缓存大小的查询方式,都有两种方式
方式1:
gv$sysstat root@10.1.150 : oceanbase 00:07:59>select * from gv$sysstat where NAME ='user block cache size' and CON_ID=1008;
+--------+--------------+----------+------------+-----------------------+-------+-----------+------------+---------+ | CON_ID | SVR_IP | SVR_PORT | STATISTIC# | NAME | CLASS | VALUE | VALUE_TYPE | STAT_ID |
+--------+--------------+----------+------------+-----------------------+-------+-----------+------------+---------+
| 1008 | 10.1.141 | 2882 | 682 | user block cache size | 16 | 160214016 | SET_VALUE | 120006 |
| 1008 | 10.1.142 | 2882 | 682 | user block cache size | 16 | 60338176 | SET_VALUE | 120006 |
+--------+--------------+----------+------------+-----------------------+-------+-----------+------------+---------+
2 rows in set (0.012 sec)
方式2:
GV$OB_KVCACHE root@10.18.92.150 : oceanbase 00:08:03>select SVR_IP,/* MONITOR_AGENT */ tenant_id, cache_name, cache_size from GV$OB_KVCACHE where tenant_id=1008 and cache_name='user_block_cache'; +--------------+-----------+------------------+------------+
| SVR_IP | tenant_id | cache_name | cache_size |
+--------------+-----------+------------------+------------+
| 10.1.142 | 1008 | user_block_cache | 60338176 |
| 10.1.141 | 1008 | user_block_cache | 160214016 |
+--------------+-----------+------------------+------------+
2 rows in set (0.035 sec)
总结:
由于 OceanBase 数据库的存储引擎是基于 LSM-Tree 架构的,所有的修改只会写入 MemTable,而 SSTable 是只读的,这就意味着 OceanBase 数据库的 Cache 是一个只读 Cache,没有刷脏页的相关逻辑,这相对于传统数据库来说会简单一些;但同时我们对存储在 SSTable 内的数据会进行数据编码和压缩,这意味着我们需要存储的数据是变长而非定长的,和传统数据库相比 Cache 的内存管理又要复杂很多。除此之外,OceanBase 数据库还是一个面向多租户的分布式数据库系统,除了和传统数据库一样要处理 Cache 的内存淘汰之外,在 Cache 内部还需要进行多租户的内存隔离。
和 Oracle 与 MySQL 类似,在 OceanBase 数据库内部,也会有很多种不同类型的 Cache,除了用于缓存 SSTable 数据的 Block Cache(类似于 Oracle 和 MySQL 的 buffer cache)之外,还有 row cache(用于缓存数据行,类似于Mysql的查询缓存)、log cache(用于缓存 redo log)、location cache(用于缓存数据副本所在的位置)、schema cache(用于缓存表的 Schema 信息)、bloom filter cache(用于缓存静态数据的 Bloomfilter,快速过滤空查)等等。OceanBase 数据库设计了一套统一的 Cache 框架,所有不同租户的不同类型的 Cache 都由框架统一管理。对于不同类型的 Cache,会配置不同的优先级,不同类型的 Cache 会根据各自的优先级以及数据访问热度做相互挤占;对于不同租户,会配置对应租户内存使用的上限和下限,不同租户的 Cache 会根据各自租户的内存上下限以及 Server 整体的内存上限做相互挤占;
一般我们只需要合理设置observer节点的总内存限制,然后合理设置租户的总内存限制,最后合理配置租户的 memstore的大小,至于 KVCache 一般不需要配置,特殊场景下可以通过参数控制各种 Cache 的优先级,优先级高的 Cache 比优先级低的 Cache 更容易被保留在 Cache 中。