OceanBase数据库全链路追踪
在OceanBase中,当用户发起一个请求后,首先会被发送给OBProxy代理,由OBProxy路由转发到OceanBase集群,进入集群中的某一个OBServer节点,随后会经过SQL引擎、存储引擎、事务引擎等(不同的请求会涉及不同引擎中的诸多处理模块),该请求也有可能通过rpc任务访问多个OBServer节点的数据,最终将结果返回给客户端。
当用户请求出现报错或者执行慢的问题时,可能是请求执行过程中的某个组件问题,也可能是不同组件节点间的网络等问题。为进一步提高分布式场景下用户请求问题诊断效率,OceanBase实现了全链路追踪机制,能够追踪用户SQL请求在数据库全链路过程中,在不同阶段、不同组件执行的相关信息,并以可视化方式展现给用户,从而帮助用户快速定位问题所在位置。
用户通过OceanBase运维平台(OCP),可以通过不同维度快速检索到有问题的请求,比如按耗时检索,按指定Trace ID或者SQL ID检索等,并且直观地看到请求从客户端到数据库内部全链路各组件的执行信息,方便快速定位出问题的阶段。
OceanBase基于各个链路的trace log,一键生成SQL的全链路耗时信息,以便用户可以快速定位链路问题。如果是通过ODP访问数据库,跟踪信息会同时记录在OBProxy(obproxy_trace.log)和OBServer的日志文件(trace.log)中;若是直接访问OBServer,则只在OBServer的日志文件中记录。
全链路追踪流程
在全链路中,不同的请求有对应的请求链路。一条完整的请求链路(Trace)则是若干个请求流程(Span)构成,在OceanBase数据库将内部处理的每一个流程定义为一个Span。请求链路可以理解为树状图,包含父节点Span以及相应的子节点Span,此部分信息会被打印到跟踪日志(trace logs)中,并通过parent_id与id来关联父子节点。
同时,在trace logs中对于每个请求流程会包含实际执行SQL信息,这部分被命名为Tag,以不同的Tag来记录当前操作的详细信息。Span和Tag被记录在trace logs中,来帮助运维人员理解数据库内部的处理逻辑以及定位问题所在。
⭐️重要概念:
- Trace:在全链路追踪流程中,Trace可以理解为OceanBase的一个事务。
- Span:属于具体某个Trace,一个Trace可以有多个Span,Span可以是语句、函数、匿名块等。
- Tag:KV,属于具体某个Span,一个Span可以有多个tag。
- Log:KV with timestamp,属于具体某个Span,一个Span可以有多个log。
常见的Span解读
- 与客户端相关的Span:
- obclient:通过OBClient客户端进行访问。
- JDBC:通过JDBC驱动进行连接。
- 与OBProxy相关的Span:
ob_proxy:为OBProxy对一条SQL处理的全部耗时,即OceanBase数据库除前端驱动层以外的从数据库请求开始到数据处理完成,结果反馈的整条链路耗时。ob_proxy_partition_location_lookup:为OBProxy在请求转发阶段,获取partition location准备进行路由的耗时。ob_proxy_server_process_req:为OBProxy对一条SQL请求的处理耗时和访问来回的网络开销。
- 与OBServer相关的Span:OBServer内部将分发过来的请求根据请求类型分为文本SQL 、preprocess statement 和存储过程三类。
- 文本SQL:
com_query_entry(同com_query_process):查询过程mpquery_single_stmt:单个语句的访问路径sql_compile:编译 SQLpc_get_plan:获取执行计划hard_parse:硬解析parse:软解析resolve:解析语法树的语义并生成语句rewrite:重写 SQLoptimize:进行基于成本的优化并生成执行计划日志code_generate:根据执行计划日志生成物理执行计划pc_add_plan:将生成的执行计划加入plan cachesql_execute:执行物理执行计划open:打开执行计划response_result:执行计划过程和结果px_schedule:按照px划分任务px_task:执行px子任务close:关闭执行计划cmd_execute:执行命令cmd_open:开启cmd计划
preprocess statement:ps_prepare:preprocess statement的预处理ps_execute:preprocess statement的执行ps_close:关闭preprocess statement
procedure:pl_entry:存储过程处理pl_compile:编译存储过程对象pc_get_pl_object:从plan cache获取存储过程对象pc_add_pl_object:把存储过程对象存储在plan cachepl_execute:执行存储过程pl_spi_query:执行存储过程中的spi语句pl_spi_prepare:存储过程预处理阶段pl_spi_execute:执行存储过程中的spi语句
常见的Tag解读
com_query_entrylog_trace_id:当前请求在log中的trace IDerr_code:当前请求的错误代码
sql_compilesess_id:session IDsql_text:SQL文本sql_id:SQL IDhit_plan:执行计划命中执行计划缓存
px_tasktask_id:并行任务的逻辑IDdfo_id:数据流操作IDsqc_id:子查询协调器IDqc_id:查询协调器IDgroup_id:资源组ID
px_scheduledfo_id:数据流操作IDused_worker_cnt:正在使用的px工作线程的个数qc_id:查询协调器ID
ps_closeps_id:preprocess statement ID
如何开启全链路追踪
前提条件
SHOW TRACE命令行查看追踪信息和通过OceanBase运维平台(OCP)查看追踪信息,使用全链路追踪对OceanBase及相关生态工具版本有一定要求。
🐯版本要求:
- OceanBase:V4.2.0及以上版本
- ODP:V4.2.0及以上版本
- JDBC:V2.4.3及以上版本
- OBClient:V2.2.3及以上版本
- OCP:V4.0.3及以上版本
使用show trace时,需使用上述正确版本并开启OceanBase 2.0协议,开启全链路诊断。
- ODP配置 :使用
root@sys用户通过ODP代理登录 OceanBase数据库、或使用root用户登录数据库的`proxysys租户后,通过执行SQL语句配置。
sql
obclient> alter proxyconfig set enable_ob_protocol_v2_with_client=true;
obclient> alter proxyconfig set enable_ob_protocol_v2=true;
- JDBC配置:
JDBC可通过URL控制开启,在JDBC URL中添加
enableFullLinkTrace=true
或者
useOceanBaseProtocolV20=true&enableFullLinkTrace=true
均可开启全链路诊断功能。
开启会话级别全链路追踪
通过客户端连接OceanBase数据库后执行如下命令开启session级别SHOW TRACE功能。
sql
obclient> set ob_enable_show_trace='on';
开启租户级别全链路追踪
OceanBase默认开启租户的全链路Trace功能。可以使用DBMS_MONITOR系统包来配置租户的全链路收集策略。
- 查询全链路Trace的收集策略。
使用root用户登录到业务租户进行查询;也可以登录到业务集群sys租户,查询的是所有租户的全链路Trace收集策略。
sql
obclient(root@sys)[oceanbase]> SELECT * FROM oceanbase.GV$OB_FLT_TRACE_CONFIG;
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| TENANT_ID | TYPE | TENANT_NAME | MODULE_NAME | ACTION_NAME | CLIENT_IDENTIFIER | LEVEL | SAMPLE_PERCENTAGE | RECORD_POLICY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| 1 | TENANT | sys | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
| 1003 | TENANT | META$1004 | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
| 1004 | TENANT | obmtest | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
| 1005 | TENANT | META$1006 | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
| 1006 | TENANT | obotest | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
5 rows in set (0.048 sec)
其中:
RECORD_POLICY字段表示trace信息输出到日志文件中策略, 支持以下三种策略:ALL:所有span和tag信息均打印到日志文件中,并且是在每个span结束时, 就打印到日志文件中。ONLY_SLOW_QUERY:当前请求为slow query,则该部分信息的span和tag会打印到日志文件中。SAMPLE_AND_SLOW_QUERY:当前请求为slow query,则该部分信息的span和tag会打印到日志文件中;其他请求信息的span和tag有一定的概率会打印到日志文件中。
SAMPLE_PERCENTAGE字段表示采样的频率。输出为10,代表采样频率为10%。LEVEL字段代表打印日志的粒度。目前支持三个粒度等级,其中Level1为模块级别的粗粒度,Level3的粒度最精细。
- 关闭当前租户的trace:
sql
obclient(root@obmtest)[oceanbase]> SELECT * FROM oceanbase.GV$OB_FLT_TRACE_CONFIG;
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| TENANT_ID | TYPE | TENANT_NAME | MODULE_NAME | ACTION_NAME | CLIENT_IDENTIFIER | LEVEL | SAMPLE_PERCENTAGE | RECORD_POLICY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| 1004 | TENANT | obmtest | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
1 row in set (0.158 sec)
obclient(root@obmtest)[oceanbase]> call dbms_monitor.ob_tenant_trace_disable();
Query OK, 0 rows affected (0.556 sec)
obclient(root@obmtest)[oceanbase]> SELECT * FROM oceanbase.GV$OB_FLT_TRACE_CONFIG;
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+---------------+
| TENANT_ID | TYPE | TENANT_NAME | MODULE_NAME | ACTION_NAME | CLIENT_IDENTIFIER | LEVEL | SAMPLE_PERCENTAGE | RECORD_POLICY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+---------------+
| 1004 | TENANT | obmtest | | | | -1 | -1 | NULL |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+---------------+
1 row in set (0.004 sec)
- 重新开启当前租户的trace:
sql
obclient(root@obmtest)[oceanbase]> call dbms_monitor.ob_tenant_trace_enable(1, 0.1, 'SAMPLE_AND_SLOW_QUERY');
Query OK, 0 rows affected (0.021 sec)
obclient(root@obmtest)[oceanbase]> SELECT * FROM oceanbase.GV$OB_FLT_TRACE_CONFIG;
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| TENANT_ID | TYPE | TENANT_NAME | MODULE_NAME | ACTION_NAME | CLIENT_IDENTIFIER | LEVEL | SAMPLE_PERCENTAGE | RECORD_POLICY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
| 1004 | TENANT | obmtest | | | | 1 | 10 | SAMPLE_AND_SLOW_QUERY |
+-----------+--------+-------------+-------------+-------------+-------------------+-------+-------------------+-----------------------+
1 row in set (0.005 sec)
⚠️生产环境谨慎开启ALL收集策略,可能会导致OpenSearch占用存储空间过大。如果当前租户已经开启全链路收集策略,需要先关闭后,再设置新的收集策略。
全链路追踪结果展示
全链路追踪信息可以通过OCP平台或者命令行查看。
OCP平台上的查看路径为:日志服务 => 链路查询。通过在链路查询界面中设置查询条件,辅助定位目标Trace。
我们也可以在OceanBase数据库的命令行界面使用Show Trace功能,在执行SQL语句后快速获取执行过程的详细调用链路和耗时信息。
sql
obclient> show variables like 'ob_enable_show_trace';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| ob_enable_show_trace | OFF |
+----------------------+-------+
1 row in set (0.003 sec)
obclient> SET ob_enable_show_trace = 1;
Query OK, 0 rows affected (0.000 sec)
obclient> select /*+parallel(2)*/ * from t_fundinfo;
...
obclient> show trace;
+---------------------------------------------------------+----------------------------+------------+
| Operation | StartTime | ElapseTime |
+---------------------------------------------------------+----------------------------+------------+
| obclient | 2025-12-19 14:14:05.481779 | 302.144 ms |
| └── com_query_process | 2025-12-19 14:14:05.493015 | 295.960 ms |
| └── mpquery_single_stmt | 2025-12-19 14:14:05.493020 | 295.942 ms |
| ├── sql_compile | 2025-12-19 14:14:05.493030 | 44.722 ms |
| │ ├── pc_get_plan | 2025-12-19 14:14:05.493035 | 0.004 ms |
| │ └── hard_parse | 2025-12-19 14:14:05.493082 | 44.661 ms |
| │ ├── parse | 2025-12-19 14:14:05.493083 | 0.041 ms |
| │ ├── resolve | 2025-12-19 14:14:05.493153 | 0.919 ms |
| │ ├── rewrite | 2025-12-19 14:14:05.494188 | 0.258 ms |
| │ ├── optimize | 2025-12-19 14:14:05.494466 | 23.152 ms |
| │ ├── code_generate | 2025-12-19 14:14:05.517641 | 19.171 ms |
| │ └── pc_add_plan | 2025-12-19 14:14:05.537075 | 0.646 ms |
| └── sql_execute | 2025-12-19 14:14:05.537769 | 251.106 ms |
| ├── open | 2025-12-19 14:14:05.537770 | 35.198 ms |
| ├── response_result | 2025-12-19 14:14:05.572998 | 215.750 ms |
| │ ├── px_schedule | 2025-12-19 14:14:05.573010 | 188.075 ms |
| │ │ ├── inner_execute_read | 2025-12-19 14:14:05.750774 | 2.112 ms |
| │ │ ├── do_local_das_task | 2025-12-19 14:14:05.753254 | 0.080 ms |
| │ │ └── px_task | 2025-12-19 14:14:05.774513 | 14.028 ms |
| │ │ ├── do_local_das_task | 2025-12-19 14:14:05.776247 | 0.072 ms |
| │ │ └── close_das_task | 2025-12-19 14:14:05.787779 | 0.006 ms |
| │ └── px_schedule | 2025-12-19 14:14:05.788723 | 0.002 ms |
| └── close | 2025-12-19 14:14:05.788761 | 0.105 ms |
| └── end_transaction | 2025-12-19 14:14:05.788846 | 0.002 ms |
+---------------------------------------------------------+----------------------------+------------+
24 rows in set (0.027 sec)
obdiag全链路功能诊断
使用obdiag analyze flt_trace命令可对OceanBase的全链路日志进行分析,给出全链路诊断报告。
使用示例
- 在
gv$ob_sql_audit视图中查找SQL的flt_trace_id。
sql
SQL> select query_sql, flt_trace_id from oceanbase.gv$ob_sql_audit where query_sql like 'select @@version_comment limit 1';
+----------------------------------+--------------------------------------+
| query_sql | flt_trace_id |
+----------------------------------+--------------------------------------+
| select @@version_comment limit 1 | 00060aa3-d607-f5f2-328b-388e17f687cb |
+----------------------------------+--------------------------------------+
⚠️ 关于
gv$ob_sql_audit返回的flt_trace_id字段值可能为空的问题:
gv$ob_sql_audit里的每一个在observer运行过的SQL记录,都会有对应的trace_id,但是flt_trace_id不一定会有,通常这是OB抽样决定的。- 如果客户端会话链路上所有组件都开通了全链路诊断对应的能力,那么这个会话发出的所有sql的
flt_trace_id都有值。这个有性能损失代价,所以不是默认行为。- 这个规则将来还可能改变。
或者也可从OBProxy、OceanBase数据库的trace.log日志中找到flt_trace_id:
bash
less trace.log
[2023-12-07 22:20:07.242229] [489640][T1_L0_G0][T1][YF2A0BA2DA7E-00060BEC28627BEF-0-0] {"trace_id":"00060bec-275e-9832-e730-7c129f2182ac","name":"close_das_task","id":"00060bec-2a20-bf9e-56c9-724cb467f859","start_ts":1701958807240606,"end_ts":1701958807240607,"parent_id":"00060bec-2a20-bb5f-e03a-5da01aa3308b","is_follow":false}
其中,00060bec-275e-9832-e730-7c129f2182ac就是其flt_trace_id。
- 执行全链路诊断命令。
bash
obdiag analyze flt_trace --flt_trace_id 00060aa3-d607-f5f2-328b-388e17f687cb
References
【1】https://www.oceanbase.com/docs/common-oceanbase-database-standalone-1000000003577635
【2】https://open.oceanbase.com/blog/18850863969
【3】https://open.oceanbase.com/blog/1775421184