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

【OceanBase DBA早下班系列】—— 如何通过 TraceID 查到对应的 OBServer 主机

数据库工兵营 2024-06-26
81

在日常定位问题的时候经常遇到通过 TraceID 来定位问题的情况,譬如通过 TraceID 定位某条 SQL 语句的详细执行信息。TraceID 可以很直观的提供某个任务的执行过程给开发人员或者运维人员。OceanBase 数据库是分布式的架构,任务执行的机器可能是未知,这导致即使有了 TraceID,依然需要在各个 OBServer 的机器上进行日志的排查。在简单的 1-1-1 的集群模式下这个任务还能接受,但是当大量 OBServer 组成的复杂集群模式场景下,仅通过定位 TraceID 找到对应的 OBServer 主机需要很多精力去做筛查。

本文讲述如何通过已有的 TraceID 信息直接定位具体任务的执行机器。

适用版本

OceanBase 数据库 所有版本。

原理解析

实际上,TraceID 确实包含具体任务执行的机器 IP 信息。TraceID 的相关定义声明在源码头文件 ob_trace_id.h
,目前有多种版本,如下:

define TRACE_ID_FORMAT "Y%lX-%016lX"
define TRACE_ID_FORMAT_V2 "Y%lX-%016lX-%lx-%lx"

但是核心的 IP 信息这块并没有大的变化。也就是日常的 ID 会以 Y
 开始紧接着是 %lX
,意味着无符号的十六进制整数,且无需 0x
 的前缀,之后用 -
 号进行分段。在 OceanBase 数据库中,IP 信息是写在前一段中的,TraceID 会将 IP 的信息拆离成四块,每一块对应 IP 中的一组数字。常见的 IP 地址分为 IPv4 与 IPv6 两大类。IPv4 的 IP 地址由一串数字组成,IPv4 为 32 位长,通常书写时以四组十进制数字组成,每组 8 位长,并以点分隔,比如:172.xx.xxx.x。

现在我们来分析如下日志里的 TraceID。

现在我们来分析如下日志里的 TraceID。

[2023-07-19 10:23:53.922556] WARN  [STORAGE.TRANS] process_cluster_heartbeat_rpc (ob_weak_read_service.cpp:485) [3359][0][YF2A7F000001-000600CD83C2AC7F-0-0] [lt=18] [dc=0] tenant weak read service process cluster heartbeat RPC fail(ret=-4341, ret="OB_NOT_IN_SERVICE", tenant_id=1002, req={req_server:"127.x.x.x:3882", version:1689733433721263, valid_part_count:152, total_part_count:152, generate_timestamp:1689733433921484}, twrs={inited:true, tenant_id:1002, self:"127.x.x.x:2882", svr_version_mgr:{server_version:{version:1689733433721263, total_part_count:152, valid_inner_part_count:149, valid_user_part_count:3, epoch_tstamp:1689733433883943}, server_version_for_stat:{version:1689733433721263, total_part_count:152, valid_inner_part_count:149, valid_user_part_count:3, epoch_tstamp:1689733433883943}}})

现在我们将日志里的 TraceID 信息进行拆解 YF2A7F000001-000600CD83C2AC7F-0-0

  • Y
     为默认开始字符。

  • 后面的分别对应端口号+IP。其中 F2A
     为端口号,7F
    00
    00
    01
     分别对应 IP 地址的四个部分,这部分使用的是 16 进制进行记录。

    具体如下:

    把每一段单独通过二进制解析可得,解析命令以及结果如下:

    [root@ob-192-168-2-51 ~]# ((PORT=0xF2A))
    [root@ob-192-168-2-51 ~]# ((IP1=0x7F))
    [root@ob-192-168-2-51 ~]# ((IP2=0x00))
    [root@ob-192-168-2-51 ~]# ((IP3=0x00))
    [root@ob-192-168-2-51 ~]# ((IP4=0x01))

    [root@ob-192-168-2-51 ~]# echo "$PORT:$IP1.$IP2.$IP3.$IP4"
    3882:127.x.x.x

    • 端口:0xF2A

    • IP 地址:0x7F000001

经过解析 TraceID,这台机器的 IP 地址为 127.x.x.x,端口为 3882。

早下班一把梭

1. 获取SQL的trace_id

从gv$ob_sql_audit中获取或者通过SELECT last_trace_id();获取

方式一:通过sql_audit中获取

    select query_sql,trace_id from oceanbase.GV$OB_SQL_AUDIT where query_sql like 'xxx%' order by REQUEST_TIME desc limit 5;

    方式二:通过当前session执行SELECT last_trace_id();获取

      SELECT last_trace_id();
      2. 执行python脚本解析trace_id获取IP地址和端口
        def get_observer_ip_from_trace_id(content):
        if content[0] == 'Y' and len(content) >= 12:
        sep = content.find('-')
        uval = int(content[1:sep], 16)
        ip = uval & 0xFFFFFFFF
        port = (uval >> 32) & 0xFFFF
        return "%d.%d.%d.%d:%d" % ((ip >> 24 & 0xFF), (ip >> 16 & 0xFF), (ip >> 8 & 0xFF), (ip >> 0 & 0xFF), port)
        else:
        return ""

        # 示例trace_id,你需要替换为实际的trace_id
        trace_id = "YB42AC1E81CB-00060AF2025B8782"

        # 调用函数并打印结果
        result = get_observer_ip_from_trace_id(trace_id)
        if result:
        print(f"Parsed IP and Port: {result}")
        else:
        print("Invalid trace_id format")

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

        评论