OceanBase內(nèi)存限制與排查思路

OceanBase的內(nèi)存限制

  • CTX內(nèi)存限制
    • 大部分 CTX 有內(nèi)存大小限制,KVCACHE 沒有。實(shí)際分配內(nèi)存時,會檢查是否超過 CTX 內(nèi)存限制,超出則報錯,比如 work area 超出限制的報錯:alloc failed reason: ctx memory has reached the upper limit(ctx_name: WORK_AREA, ctx_hold: 320864256, ctx_limit: 322122545, alloc_size: 2097152)
  • 租戶內(nèi)存限制
    • 租戶內(nèi)所有 CTX 的內(nèi)存大小設(shè)置加起來允許超過租戶內(nèi)存大小
    • 實(shí)際分配內(nèi)存時,如果超過租戶內(nèi)存大小限制,會報錯: No memory or reach tenant memory limit( msg=tenant memory has reached the )
  • observer 級別的內(nèi)存限制
    • 創(chuàng)建租戶時所有租戶內(nèi)存+system_memory(500租戶預(yù)留內(nèi)存) 不能超過這個限制
    • 500 租戶的內(nèi)存實(shí)際沒有上限
    • 集群運(yùn)行時,所有租戶實(shí)際分配內(nèi)存時,如果超過這個限制,會報錯 over total memory limit。

內(nèi)存排查思路

內(nèi)存排查順序:

  1. server 級別:gv$sysstat、__all_virtual_server_memory_info
  2. 租戶級別:gv$tenant_memory_info
  3. 上下文級別:__all_virtual_tenant_ctx_memory_info
  4. mod 級別:__all_virtual_memory_info、gv$memory

下面用 3 個示例展示不同級別內(nèi)存超限的表現(xiàn)。

1. server 級別內(nèi)存超限

報錯:超出 observer 總內(nèi)存

日志解讀:

  • oops, over total memory limit, hold=13128171520 limit=13324949913 表示超過了 observer 的內(nèi)存上限
  • oops, alloc failed, tenant_id=500 表示SQL執(zhí)行時 500 租戶分配內(nèi)存報錯,超過了observer 的內(nèi)存上限

1.1 通過 __all_virtual_server_memory_info 查看 OBServer 的內(nèi)存使用情況:

  • server_memory_limit 即為每個 observer 的內(nèi)存上限
  • server_memory_hold:OBServer已分配內(nèi)存
  • system_reserved:為500租戶保留的內(nèi)存,由system_memory直接指定。但是這個不是硬限制,只是預(yù)留給 500租戶的,實(shí)際上可以超過這個值。

此案例中報錯太快,查詢 __all_virtual_server_memory_info 來不及觀察到 server 內(nèi)存用滿

obclient [oceanbase]> select * from __all_virtual_server_memory_info;
+--------------+----------+--------------------+---------------------+-----------------+----------------------+---------------------+----------------------+----------------+
| svr_ip       | svr_port | server_memory_hold | server_memory_limit | system_reserved | active_memstore_used | total_memstore_used | major_freeze_trigger | memstore_limit |
+--------------+----------+--------------------+---------------------+-----------------+----------------------+---------------------+----------------------+----------------+
| 10.186.58.85 |     2882 |        13058965504 |         13324949913 |      1073741824 |            695938400 |           704643072 |           7350724853 |     8575845662 |
| 10.186.58.87 |     2882 |        13077839872 |         13323580211 |      1073741824 |            637244800 |           645922816 |           7349903032 |     8574886870 |
| 10.186.58.86 |     2882 |        13031702528 |         13324949913 |      1073741824 |            628860000 |           637534208 |           7350724853 |     8575845662 |
+--------------+----------+--------------------+---------------------+-----------------+----------------------+---------------------+----------------------+----------------+
3 rows in set (0.029 sec)

1.2 查看 500 租戶的 CTX 內(nèi)存使用情況

500租戶中 DEFAULT_CTX_ID 這個內(nèi)存上下文使用的內(nèi)存最多:

obclient [oceanbase]> SELECT tenant_id,ctx_name, sum(hold) FROM __all_virtual_tenant_ctx_memory_info WHERE svr_ip = '10.186.58.85' AND svr_port=2882 and tenant_id=500 GROUP BY ctx_name HAVING sum(hold)>0 order by 3 desc;
+-----------+--------------------------------+------------+
| tenant_id | ctx_name                       | sum(hold)  |
+-----------+--------------------------------+------------+
|       500 | DEFAULT_CTX_ID                 | 5314183168 |
|       500 | CO_STACK                       | 1992987216 |
|       500 | STORAGE_SHORT_TERM_META_CTX_ID |  220200960 |
|       500 | LIBEASY                        |  195035136 |
|       500 | GLIBC                          |  171966464 |
|       500 | STORAGE_LONG_TERM_META_CTX_ID  |   46137344 |
|       500 | LOGGER_CTX_ID                  |   29360128 |
|       500 | WORK_AREA                      |   16777216 |
|       500 | REPLAY_STATUS_CTX_ID           |   14680064 |
+-----------+--------------------------------+------------+
9 rows in set (0.004 sec)

1.3 查看 500 租戶中具體 mode 的內(nèi)存使用情況

obclient [oceanbase]> select ctx_name,mod_name, mod_type, round(sum(hold)/1024/1024) as hold_mb,  round(sum(used)/1024/1024) as used_mb, sum(count) as count from __all_virtual_memory_info where  tenant_id=500 and svr_ip= '10.186.58.85' group by ctx_name, mod_name,mod_type order by used_mb desc, count desc limit 10;
+----------------+------------------+----------+---------+---------+-------+
| ctx_name       | mod_name         | mod_type | hold_mb | used_mb | count |
+----------------+------------------+----------+---------+---------+-------+
| CO_STACK       | CO_STACK         | user     |    1901 |    1901 |     1 |
| DEFAULT_CTX_ID | CallbackTask     | user     |     812 |     809 |   223 |
| DEFAULT_CTX_ID | LinearHashMap    | user     |     494 |     493 |  7090 |
| DEFAULT_CTX_ID | ConcurObjPool    | user     |     421 |     418 |  4639 |
| DEFAULT_CTX_ID | OB_KVSTORE_CACHE | user     |     270 |     264 |    10 |
| GLIBC          | glibc_malloc     | user     |     156 |     135 | 39938 |
| DEFAULT_CTX_ID | FixeSizeBlocAll  | user     |     136 |     128 |     5 |
| DEFAULT_CTX_ID | LogHotCache      | user     |     132 |     128 |     2 |
| DEFAULT_CTX_ID | LightyQueue      | user     |     149 |     127 |    39 |
| DEFAULT_CTX_ID | ClogMgr          | user     |     122 |     120 |     5 |
+----------------+------------------+----------+---------+---------+-------+
10 rows in set (0.032 sec)

結(jié)論:500租戶使用內(nèi)存過多,測試租戶分配內(nèi)存時,所有租戶使用的總內(nèi)存加起來超過了 memory_limit 限制,導(dǎo)致分配內(nèi)存報錯。500租戶的 DEFAULT_CTX_ID 上下文使用內(nèi)存最多,其中又以 CallbackTask、LinearHashMap、ConcurObjPool 這3個 mode 使用的內(nèi)存最多,無法看出原因。測試環(huán)境中嘗試重啟集群,只釋放了少量 500 租戶內(nèi)存。

2. 租戶內(nèi)存超限

報錯租戶總內(nèi)存超限,具體報在 plan cache 上。日志如下:

2.1查看租戶總使用內(nèi)存:

select * from gv$tenant_memory_info where tenant_id=1002;

2.2 查看租戶的CTX內(nèi)存使用情況:

SELECT tenant_id,ctx_name, sum(hold) FROM __all_virtual_tenant_ctx_memory_info WHERE svr_ip = '10.186.58.85' AND svr_port=2882 and tenant_id=1002 GROUP BY ctx_name HAVING sum(hold)>0 order by 3 desc;

2.3 查看租戶的 mode 內(nèi)存使用情況:
select * from gv$memory where tenant_id=1002 and IP='10.186.58.85' order by USED desc limit 10;
或者:
select ctx_name,mod_name, mod_type, round(sum(hold)/1024/1024) as hold_mb, round(sum(used)/1024/1024) as used_mb, sum(count) as count from __all_virtual_memory_info where tenant_id=1002 and svr_ip= '10.186.58.85' group by ctx_name, mod_name,mod_type order by used_mb desc, count desc limit 10;

結(jié)論:這個例子中報錯太快了,來不及觀察租戶哪塊內(nèi)存使用量增加明顯(包括日志中每隔10秒輸出的內(nèi)存使用情況也抓不到),報錯后再觀察已經(jīng)看不出異常??偟膩碚f是租戶總使用內(nèi)存太多,當(dāng)獲取 plan cache 時已經(jīng)超出租戶內(nèi)存上限,然后報錯,這不是 plan cache 設(shè)置太大導(dǎo)致的。

3. work area 內(nèi)存上下文超限

work area 超出限制,日志表現(xiàn):

解決:調(diào)大租戶變量ob_sql_work_area_percentage

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 內(nèi)存結(jié)構(gòu) OBserver的內(nèi)存,由兩個參數(shù)共同決定,如果沒有設(shè)置memory-limit參數(shù),可使用內(nèi)存為物理內(nèi)...
    hafe閱讀 625評論 0 1
  • LSM是一種不可變存儲結(jié)構(gòu),將隨機(jī)IO轉(zhuǎn)化為順序化,對文件的寫減少了鎖和閂鎖的操作,使得寫入并發(fā)訪問。 RUM,B...
    hafe閱讀 661評論 0 0
  • 優(yōu)化器規(guī)則 優(yōu)化器根據(jù)統(tǒng)計(jì)信息和代價模型([RBO] 、[CBO])為每個執(zhí)行計(jì)劃計(jì)算一個代價,代價是對執(zhí)行計(jì)劃的...
    hafe閱讀 1,240評論 0 1
  • 創(chuàng)建docker網(wǎng)絡(luò) docker network create -d bridge bridge1 容器之間涉及...
    idealheap閱讀 436評論 0 0
  • 參考資料 如何管理 OceanBase 數(shù)據(jù)庫連接[https://www.oceanbase.com/docs/...
    輕松的魚閱讀 1,418評論 0 2

友情鏈接更多精彩內(nèi)容