本文介绍如何排查 schema 或 session 泄露问题。
OceanBase 数据库中 schema 槽位泄漏导致的内存不断上涨。即使槽位的泄露也会导致内存不断上涨,原因如下:
引用是 get_tenant_schema_schema_guard 瞬间产生,reset 或者析构时释放。
占用所有槽位会导致内存增长速度变快。
占用部分槽位时只要有一个引用计数没释放,schema 就无法 switch_allocator 释放内存,后续随着 DDL 的执行,新增的 schema 版本会放在同一个 allocator 上,泄漏速度比占满所有槽位略慢。
排查 schema 或 session 泄露的思路
确认 schema 是否有泄漏。
通过
SCHEMA_STATISTICS关键词过滤 observer 日志文件找到ref_cnt不为 0 的最小 schema 版本号 schema_version 值。grep 'SCHEMA_STATISTICS' observer.log输出结果如下:
observer.log.20220606105744:[2022-06-06 10:57:41.996468] INFO [SHARE.SCHEMA] ob_schema_mgr_cache.cpp:549 [366548][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=126] [SCHEMA_STATISTICS]dump schema_mgr_item( i=17, ret=0, tenant_id=1002, schema_version=1654219558961856, schema_count=5346, schema_size=15782482, ref_cnt=1, mod_ref_cnt=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]) observer.log.20220606105744:[2022-06-06 10:57:42.003731] INFO [SHARE.SCHEMA] ob_schema_mgr_cache.cpp:549 [366548][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=162] [SCHEMA_STATISTICS] dump schema_mgr_item( i=22, ret=0, tenant_id=1002, schema_version=1654345586613792, schema_count=4469, schema_size=13714700, ref_cnt=1, mod_ref_cnt=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0])示例日志指出,1002 租户仍引用两个旧的 schema 版本(6 月 3 日和 6 月 4 日的),可能存在泄露。
schema_version=1654219558961856 = 6月3日09:25 schema_version=1654345586613792 = 6月4日20:26
确认是否有 session 泄漏。
通过
get current session count关键词过滤 observer 日志文件获取当前会话数。检查分配出去的 session 数(used_session_count)和 session mgr 中记录的 session 数(hold_session_count)是否相等。如果这两个计数不一致,可能存在 session 泄漏。grep 'get current session count' observer.log.2022060611*输出结果如下:
observer.log.20220606110048:[2022-06-06 11:00:43.344867] INFO [SQL] ob_sql_session_mgr.cpp:487 [366332][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=6] get current session count( used_session_count=1825, hold_session_count=1825, session_leak_count_threshold=100) observer.log.20220606110203:[2022-06-06 11:01:58.651943] INFO [SQL] ob_sql_session_mgr.cpp:487 [366332][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=6] get current session count( used_session_count=1928, hold_session_count=1928, session_leak_count_threshold=100)示例日志显示,两个计数相等,意味着分配的 session 均被正常管理,说明不存在泄露,若想整体了解 session 信息可查看视图
__all_virtual_session_info。注意
并发场景下,存在两个数不一致的情况,并发后会保持一致。
确认是否有长 Query。
查看数据库的内部表
__all_virtual_session_info,发现长时间运行的 SQL(即使已经尝试 kill 掉,但没有退出)所处的 session 信息。
进一步确认 session 具体情况可通过
pstack线程号在堆栈中确定进程卡在哪里,另外也可采用top -H来查看线程的 CPU 使用情况,判断是否陷入死循环。
内部表 __all_virtual_session_info 和__all_virtual_processlist 的区别
用途不同。
内部表
__all_virtual_session_info是面向内核的,包含 session mgr 中所有 session 状态 ACTIVE、SLEEP、KILLED、REMOTE SESSION 等。内部表
__all_virtual_processlist是用户层面,仅展示与用户连接相关的session 信息。该视图主要用于了解当前连接到数据库的用户进程信息。
内容不一样。
内部表
__all_virtual_session_info包含ref_count、backtrace、thread_id等诊断内容,常用于查 bug。内部表
__all_virtual_processlist只是展示会话信息。
两个内部表的主要区别在于它们的使用目的和提供的信息范围,前者用于内核诊断,后者用于用户级的进程信息展示。
适用版本
OceanBase 数据库所有版本。