暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何找出 OceanBase 转储的热点表?

120

作者:郑增权,爱可生 DBA 团队成员,OceanBase 和 MySQL 数据库技术爱好者。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 2500 字,预计阅读需要 8 分钟。


1. 背景

1.1 客户疑问

某个租户一直在频繁的转储,有什么方法可以找到是哪些 SQL 语句导致的?

1.2 环境信息

OB V 4.2.1.10

2. 基础知识

2.1 LSM Tree 存储架构

  1. OceanBase 数据库的租户内部的内存总体上分为两类:
    1. 可伸缩内存(KVCache 等)
    2. 不可伸缩内存(MemStore 等)。
  2. 写数据( DML 操作)时首先会写入内存区(MemStore)。
  3. memstore_limit_percentage :用于设置租户使用 MemStore 的内存占其总可用内存的百分比,默认值是 50%。

2.2 MemTable 中的数据结构

2.2.1 两种数据结构的特点

  1. 我们可以认为 MemStore 是一个容器,容器内部由多个 MemTable 组成。
  2. 一个分区对应一个 MemTable(非分区表对应一个 MemTable,分区表则对应多个 MemTable)。
  3. 在 插入/更新/删除 数据时,根据数据涉及的范围选择 HashTable 或者 BTree 找到或更新对应的数据。
  • HashTable 的优点:插入一行数据的时候,需要先检查此行数据是否已经存在,当且仅当数据不存在时才能插入,检查冲突时,用 Hashtable 要比 BTree 快。 事务在插入或更新一行数据的时候,需要找到此行并对其进行上锁,防止其它事务修改此行,OceanBase 数据库的行锁放在行头数据结构中,需要先找到它,才能上锁。

  • HashTable 的缺点:不适合对范围查询使用 HashTable。

  • BTree 的优点:范围查找时,由于 BTree 中的数据都是有序的,因此只需要搜索局部的数据就可以了。

  • BTree 的缺点:单行的查找,也需要进行大量的主键比较,从根结点找到叶子结点,而主键比较性能是较差的,因此理论上性能比 HashTable 慢很多。

2.3 Mini Compaction(转储)

  1. 转储(Mini Compaction 或称之为 Mini Merge):当租户的 MemTable 大小超过 freeze_trigger_percentage (默认值 20%)的值时,对内存中的数据进行冻结(Freeze)并转储为 Mini SSTable ,然后统一释放这些 MemTable 占用的内存。
    • 转储是租户级别,而不是集群级别。
  2. 转储是 OBServer 级别的,每个 OBServer 根据租户在该节点的 MemStore 使用情况单独触发转储。
    • 自动转储时,会将 MemStore 中所有分区的 MemTable 均冻结和转储,而不是针对某个分区。

3. 实验

3.1 建表并插入数据

往 test_table
 表插入 10 万条数据。

MySQL [evan]> show createtable test_table;
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | CreateTable                                                                                                                                                                                                                                                                                                                                                                                           |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_table | CREATETABLE`test_table` (
`id`bigint(20) NOTNULL AUTO_INCREMENT,
`name`varchar(50) DEFAULTNULL,
`create_time` datetime DEFAULTNULL,
  PRIMARY KEY (`id`)
) AUTO_INCREMENT = 39998 AUTO_INCREMENT_MODE = 'ORDER'DEFAULTCHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1rowinset (0.01 sec)
MySQL [evan]> CALL insert_test_data();

往表 test_users
 插入 1000 条数据。

-- Creating test_users table
CREATE TABLE test_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    register_date DATETIME NOT NULL
);

CALL insert_test_users();

3.2 业务租户执行转储

MySQL [allen]> alter system minor freeze;
Query OK, 0 rows affected (0.11 sec)

3.3 查看正在转储的表的 tablet_id

  • tablet_id
     为 49401、49402 的是 OB 内部事务状态表,需要排除,无需关注。
  • tablet_id
    • 很短的一般都是系统的表,无需关注。
    • 很长的可能是索引之类的,可以查看所属的表是哪个。
    • 我们主要关注业务表,业务表 table_id
       一般是 6 位数。
  • ACTION 为 MINI_MERGE:Mini Compaction,将 MemTable 转变成 Mini SSTable。
  • MACRO_BLOCK_COUNT:Compaction 宏块总数。

SQL 1:查看 1002 租户一天的转储情况,Compaction 宏块总数降序排序,取前 10 条结果。

MySQL [oceanbase]> SELECT SVR_IP,TENANT_ID,LS_ID,TABLET_ID,ACTION,MACRO_BLOCK_COUNT,COMPACTION_SCN,START_TIME,END_TIME  FROM oceanbase.GV$OB_MERGE_INFO WHERE TENANT_ID = 1002AND LS_ID <> 1AND tablet_id notin ( 49401,49402) ANDACTION='MINI_MERGE'AND START_TIME LIKE'2025-06-26%'ORDERBY MACRO_BLOCK_COUNT DESCLIMIT10;
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| SVR_IP       | TENANT_ID | LS_ID | TABLET_ID | ACTION     | MACRO_BLOCK_COUNT | COMPACTION_SCN      | START_TIME                 | END_TIME                   |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:24.317534 | 2025-06-26 22:33:24.544235 |
| 10.186.65.8  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:27.144210 | 2025-06-26 22:33:27.415615 |
| 10.186.65.9  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403793514050 | 2025-06-26 22:33:25.361842 | 2025-06-26 22:33:26.058388 |
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:23.916445 | 2025-06-26 21:36:23.967620 |
| 10.186.65.8  |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:21.704055 | 2025-06-26 21:36:21.812143 |
| 10.186.65.9  |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:23.889711 | 2025-06-26 21:36:24.165441 |
| 10.186.65.23 |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:24.318647 | 2025-06-26 22:33:24.338969 |
| 10.186.65.8  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:27.190671 | 2025-06-26 22:33:27.195573 |
| 10.186.65.9  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:25.369246 | 2025-06-26 22:33:25.380798 |
| 10.186.65.23 |      1002 |  1003 |    200004 | MINI_MERGE |                 0 | 1749261600449876665 | 2025-06-26 10:00:48.110727 | 2025-06-26 10:00:48.114597 |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
10 rows in set (0.14 sec)


按照涉及的宏块总数来看,200006 这个 tablet 对应的表对于 memstore 的占用是最高的。

SQL 2:查看 1002 租户最新的转储情况,取前 10 条结果。

MySQL [oceanbase]> SELECT SVR_IP,TENANT_ID,LS_ID,TABLET_ID,ACTION,MACRO_BLOCK_COUNT,COMPACTION_SCN,START_TIME,END_TIME  FROM oceanbase.GV$OB_MERGE_INFO WHERE TENANT_ID = 1002AND LS_ID <> 1AND tablet_id notin (49401,49402) ANDACTION='MINI_MERGE'AND START_TIME LIKE'2025-06-26%'ORDERBY START_TIME DESCLIMIT10;
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| SVR_IP       | TENANT_ID | LS_ID | TABLET_ID | ACTION     | MACRO_BLOCK_COUNT | COMPACTION_SCN      | START_TIME                 | END_TIME                   |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| 10.186.65.8  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:27.190671 | 2025-06-26 22:33:27.195573 |
| 10.186.65.8  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:27.144210 | 2025-06-26 22:33:27.415615 |
| 10.186.65.9  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:25.369246 | 2025-06-26 22:33:25.380798 |
| 10.186.65.9  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403793514050 | 2025-06-26 22:33:25.361842 | 2025-06-26 22:33:26.058388 |
| 10.186.65.23 |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:24.318647 | 2025-06-26 22:33:24.338969 |
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:24.317534 | 2025-06-26 22:33:24.544235 |
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:23.916445 | 2025-06-26 21:36:23.967620 |
| 10.186.65.9  |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:23.889711 | 2025-06-26 21:36:24.165441 |
| 10.186.65.8  |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:21.704055 | 2025-06-26 21:36:21.812143 |
| 10.186.65.9  |      1002 |  1001 |    200001 | MINI_MERGE |                 0 |                   1 | 2025-06-26 10:03:21.758154 | 2025-06-26 10:03:21.850344 |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
10 rows in set (0.34 sec)

3.4 根据 tablet_id
 查询表名

  1. 通过 sys 租户执行 SQL 。
  2. CON_ID:是租户 id,请根据实际替换。
  3. OWNER:数据库名称。
  4. OBJECT_NAME:对象名称(表名)。
  5. 此处我们主要查询 tablet_id
     为 200006 和 200007 对应的表。
SELECT CON_ID,OWNER,OBJECT_NAME,OBJECT_TYPE,SUBOBJECT_NAME, OBJECT_ID,DATA_OBJECT_ID from oceanbase.CDB_OBJECTS  WHERE CON_ID = 1002 AND DATA_OBJECT_ID = '200006';
+--------+-------+-------------+-------------+----------------+-----------+----------------+
| CON_ID | OWNER | OBJECT_NAME | OBJECT_TYPE | SUBOBJECT_NAME | OBJECT_ID | DATA_OBJECT_ID |
+--------+-------+-------------+-------------+----------------+-----------+----------------+
|   1002 | evan  | test_table  | TABLE       | NULL           |    500012 |         200006 |
+--------+-------+-------------+-------------+----------------+-----------+----------------+
1 row in set (0.16 sec)

MySQL [oceanbase]> SELECT CON_ID,OWNER,OBJECT_NAME,OBJECT_TYPE,SUBOBJECT_NAME, OBJECT_ID,DATA_OBJECT_ID from oceanbase.CDB_OBJECTS  WHERE CON_ID = 1002 AND DATA_OBJECT_ID = '200007';
+--------+-------+-------------+-------------+----------------+-----------+----------------+
| CON_ID | OWNER | OBJECT_NAME | OBJECT_TYPE | SUBOBJECT_NAME | OBJECT_ID | DATA_OBJECT_ID |
+--------+-------+-------------+-------------+----------------+-----------+----------------+
|   1002 | allen | test_users  | TABLE       | NULL           |    500016 |         200007 |
+--------+-------+-------------+-------------+----------------+-----------+----------------+
1 row in set (0.09 sec)

3.5 查看两个表涉及的 DML 相关的 SQL

可以看到是前面执行的造数调用的存储过程的 SQL 语句。

-- test_table 表
MySQL [oceanbase]> select svr_ip,trace_id,sql_id,usec_to_time(request_time),query_sql from gv$ob_sql_audit where tenant_id =1002 and query_sql like 'insert%test_table%' or query_sql like 'INSERT%test_table%' or query_sql like 'delete%test_table%' or query_sql like 'DELETE%test_table%' or query_sql like 'update%test_table%' or query_sql like 'UPDATE%test_table%' order by elapsed_time desc limit 1;
+-------------+-----------------------------------+----------------------------------+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| svr_ip      | trace_id                          | sql_id                           | usec_to_time(request_time) | query_sql                                                                                                                                                                                                                                        |
+-------------+-----------------------------------+----------------------------------+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 10.186.65.9 | YB420ABA4109-000635FFFC8AF16E-0-0 | D0A0BE901EA6BFE0DA916255FFBF954B | 2025-06-26 22:33:28.006047 | INSERTINTO test_table (name, create_time)
        VALUES (
            CONCAT('user_', :0), -- Generates names like 'user_1', 'user_2', etc.
            NOW() - INTERVAL FLOOR(RAND() * 365) DAY-- Random date within the last year
        ) |
+-------------+-----------------------------------+----------------------------------+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row inset (0.35 sec)


-- test_users 表(同理,不做重复粘贴)
select svr_ip,trace_id,sql_id,usec_to_time(request_time),query_sql from gv$ob_sql_audit where tenant_id =1002 and query_sql like 'insert%test_users%' or query_sql like 'INSERT%test_users%' or query_sql like 'delete%test_users%' or query_sql like 'DELETE%test_users%' or query_sql like 'update%test_users%' or query_sql like 'UPDATE%test_users%' order by elapsed_time desc limit 1;

3.6 进一步验证语句的有效性

往 test_users
 表再插入 20W 条数据。

MySQL [allen]>  CALL insert_test_users();
Query OK, 1 row affected (9 min 8.23 sec)

3.7 再次查看 1002 租户一天的转储情况

可以看到 tablet 200007 涉及的宏块总数由 1 增长到 2 或者 3 了。

MySQL [oceanbase]> SELECT SVR_IP,TENANT_ID,LS_ID,TABLET_ID,ACTION,MACRO_BLOCK_COUNT,COMPACTION_SCN,START_TIME,END_TIME  FROM oceanbase.GV$OB_MERGE_INFO WHERE TENANT_ID = 1002 AND LS_ID <> 1 AND tablet_id not in (49401,49402) AND ACTION='MINI_MERGE' AND START_TIME LIKE '2025-06-26%' ORDER BY MACRO_BLOCK_COUNT DESC LIMIT 10;
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| SVR_IP       | TENANT_ID | LS_ID | TABLET_ID | ACTION     | MACRO_BLOCK_COUNT | COMPACTION_SCN      | START_TIME                 | END_TIME                   |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
| 10.186.65.23 |      1002 |  1003 |    200007 | MINI_MERGE |                 3 | 1750949839751752853 | 2025-06-26 22:57:24.442409 | 2025-06-26 22:57:24.778592 |
| 10.186.65.8  |      1002 |  1003 |    200007 | MINI_MERGE |                 3 | 1750949798303843049 | 2025-06-26 22:56:42.263684 | 2025-06-26 22:56:42.599886 |
| 10.186.65.9  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403793514050 | 2025-06-26 22:33:25.361842 | 2025-06-26 22:33:26.058388 |
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:24.317534 | 2025-06-26 22:33:24.544235 |
| 10.186.65.8  |      1002 |  1002 |    200006 | MINI_MERGE |                 2 | 1750948403741623375 | 2025-06-26 22:33:27.144210 | 2025-06-26 22:33:27.415615 |
| 10.186.65.9  |      1002 |  1003 |    200007 | MINI_MERGE |                 2 | 1750949784654232477 | 2025-06-26 22:56:25.246718 | 2025-06-26 22:56:26.265284 |
| 10.186.65.23 |      1002 |  1002 |    200006 | MINI_MERGE |                 1 | 1750944980577137690 | 2025-06-26 21:36:23.916445 | 2025-06-26 21:36:23.967620 |
| 10.186.65.8  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750949932352151540 | 2025-06-26 22:59:32.283314 | 2025-06-26 22:59:32.365460 |
| 10.186.65.9  |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750949932352151540 | 2025-06-26 22:59:25.293952 | 2025-06-26 22:59:25.648741 |
| 10.186.65.23 |      1002 |  1003 |    200007 | MINI_MERGE |                 1 | 1750948403497631799 | 2025-06-26 22:33:24.318647 | 2025-06-26 22:33:24.338969 |
+--------------+-----------+-------+-----------+------------+-------------------+---------------------+----------------------------+----------------------------+
10 rows in set (0.30 sec)

4. 结论

  1. 租户若频繁转储,一般是由于 DML 操作导致,单纯的查询主要占用 KVCache 部分的内存,占用 MemStore 不大,自然也不会导致频繁的转储。
  2. 租户转储动作会产生对于宏块的变更,当转储时某个 tablet 涉及的宏块数量较大时,一般我们需要关注它对应的 DML 操作是否合理并采取对应的措施。

5. 参考资料

  1. 《MemTable》:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002014004
  2. 《GV$OB_MERGE_INFO》: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002014914

本文关键字:#OceanBase #热点表





2000 倍性能提升!Semi Join 改写全过程分析
3.X vs 4.X:OceanBase 手动收集统计信息的天壤之别!
一个案例掌握 OMS 校验方式及适用场景
OBLogProxy 在 Binlog 模式下的故障案例解析



✨ Github:https://github.com/actiontech/sqle

📚 文档:https://actiontech.github.io/sqle-docs/

💻 官网:https://opensource.actionsky.com/sqle/

👥 微信群:请添加小助手加入 ActionOpenSource

🔗 商业支持:https://www.actionsky.com/sqle


文章转载自爱可生开源社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论