走进SQL审计视图——《OceanBase诊断系列》之二

2024-03-05 1660阅读

温馨提示:这篇文章已超过386天没有更新,请注意相关的内容是否还可用!

1. 前言

在SQL性能诊断上,OceanBase有一个非常实用的功能 —— SQL审计视图(gv$sql_audit)。在OceanBase 4.0.0及更高版本中,该功能是 gv$ob_sql_audit。它可以使开发和运维人员更方便地排查在OceanBase上运行过的任意一条SQL,无论这些SQL是成功与否,都有详细的运行信息记录。这些信息包括客户端和服务端的IP端口、SQL语句、执行时间、执行节点、执行计划ID、会话ID、执行时间、等待时间、总时间、排队时间、以及相关的块读取信息和执行报错信息等。

查询方式说明
(g)v$ob_sql_auditOceanBase 4.0.0.0 及以上版本,gv$xx查询该租户所有机器v$xxx查询该租户本机器(不保证路由准确)
(g)v$sql_auditOceanBase 4.0.0.0 以下版本gv$xx查询该租户所有机器v$xxx查询该租户本机器(不保证路由准确)

sql_audit是基于虚拟表__all_virtual_sql_audit的视图, 该虚拟表对应的数据存放在一个可配置的内存空间中,能够记录并显示每一次SQL请求的来源、执行状态及统计信息,由于存放这些记录的内存是有限的,因此到达一定内存使用量,会触发淘汰。

  • sql_audit 每隔 1s 会检测后台任务并根据以下标准决定是否淘汰:
    • sql_audit 内存最大可使用上限为 avail_mem_limit = min (OBServer 可使用内存 *10%,sql_audit_memory_limit)。
    • 当 avail_mem_limit 在 [64M, 100M] 范围内时, 内存使用达到 avail_mem_limit-20M 时触发淘汰。
    • 当 avail_mem_limit 在 [100M, 5G] 范围内时, 内存使用达到 availmem_limit*0.8 时触发淘汰。
    • 当 avail_mem_limit 在 [5G, +∞)范围内时, 内存使用达到 availmem_limit-1G 时触发淘汰。
    • 当 sql_audidt 记录数超过 900 万条时,触发淘汰。
  • sql_audit 根据以下标准决定是否停止淘汰:
    • 如果是达到内存上限触发淘汰则:
    • 当 avail_mem_limit 在 [64M, 100M] 时, 内存使用淘汰到 avail_mem_limit-40M 时停止淘汰。
    • 当 avail_mem_limit 在 [100M, 5G] 时, 内存使用淘汰到 availmem_limit*0.6 时停止淘汰。
    • 当 avail_mem_limit 在 [5G, +∞] 时, 内存使用淘汰到 availmem_limit-2G 时停止淘汰。
    • 如果是达到记录数上限触发的淘汰则淘汰到 800 万行记录时停止淘汰。

    2. sql_audit视图字段介绍

    字段名称类型描述
    SVR_IPvarchar(32)ip地址
    SVR_PORTbigint(20)端口号
    REQUEST_IDbigint(20)请求的id号
    TRACE_IDvarchar(128)这条语句的trace_id
    CLIENT_IPvarchar(32)发送请求的client ip
    CLIENT_PORTbigint(20)发送请求的client port
    TENANT_IDbigint(20)发送请求的租户id
    TENANT_NAMEvarchar(64)发送请求的租户 名称
    USER_IDbigint(20)发送请求的用户id
    USER_NAMEvarchar(64)发送请求的用户名称
    SQL_IDvarchar(32)这条SQL的id
    QUERY_SQLvarchar(32768)实际的SQL语句
    PLAN_IDbigint(20)执行计划id
    AFFECTED_ROWSbigint(20)影响行数
    RETURN_ROWSbigint(20)返回行数
    PARTITION_CNTbigint(20)该请求涉及的分区数
    RET_CODEbigint(20)执行结果返回码
    EVENTvarchar(64)最长等待事件名称
    P1TEXTvarchar(64)等待事件参数1
    P1bigint(20) unsigned等待事件参数1的值
    P2TEXTvarchar(64)等待事件参数2
    P2bigint(20) unsigned等待事件参数2的值
    P3TEXTvarchar(64)等待事件参数3
    P3bigint(20) unsigned等待事件参数3的值
    LEVELbigint(20)等待事件的level级别
    WAIT_CLASS_IDbigint(20)等待事件所属的class id
    WAIT_CLASS#bigint(20)等待事件所属的class 的下标
    WAIT_CLASSvarchar(64)等待事件所属的class 名称
    STATEvarchar(19)等待事件的状态
    WAIT_TIME_MICRObigint(20)该等待事件所等待的时间
    TOTAL_WAIT_TIME_MICRObigint(20)执行过程所有等待的总时间
    TOTAL_WAITSbigint(20)执行过程总等待的次数
    RPC_COUNTbigint(20)发送rpc个数
    PLAN_TYPEbigint(20)执行计划类型
    IS_INNER_SQLtinyint(4)是否内部sql请求
    IS_EXECUTOR_RPCtinyint(4)当前请求是否rpc请求
    IS_HIT_PLANtinyint(4)是否命中plan_cache
    REQUEST_TIMEbigint(20)开始执行时间点
    ELAPSED_TIMEbigint(20)接收到请求到执行结束消耗 总时间
    NET_TIMEbigint(20)发送rpc到接收到请求时间
    NET_WAIT_TIMEbigint(20)接收到请求到进入队列时间
    QUEUE_TIMEbigint(20)请求在队列等待事件
    DECODE_TIMEbigint(20)出队列后decode时间
    GET_PLAN_TIMEbigint(20)开始process到获得plan时间
    EXECUTE_TIMEbigint(20)plan执行消耗时间
    APPLICATION_WAIT_TIMEbigint(20) unsigned所有application类事件的总时间
    CONCURRENCY_WAIT_TIMEbigint(20) unsigned所有concurrency类事件的总时间
    USER_IO_WAIT_TIMEbigint(20) unsigned所有user_io类事件的总时间
    SCHEDULE_TIMEbigint(20) unsigned所有schedule类事件的时间
    ROW_CACHE_HITbigint(20)行缓存命中次数
    BLOOM_FILTER_CACHE_HITbigint(20)bloom filter缓存命中次数
    BLOCK_CACHE_HITbigint(20)块缓存命中次数
    BLOCK_INDEX_CACHE_HITbigint(20)块索引缓存命中次数
    DISK_READSbigint(20)物理读次数
    EXECUTION_IDbigint(20)执行ID
    SESSION_IDbigint(20)session id
    RETRY_CNTbigint(20)重试次数
    TABLE_SCANtinyint(4)判断该请求是否含全表扫描
    CONSISTENCY_LEVELbigint(20)一致性级别
    MEMSTORE_READ_ROW_COUNTbigint(20)MEMSTORE中的读行数
    SSSTORE_READ_ROW_COUNTbigint(20)SSSTORE中读的行数
    REQUEST_MEMORY_USEDbigint(20)该请求消耗的内存
    • 一些重要的事件间隔

      走进SQL审计视图——《OceanBase诊断系列》之二

      3. 基于sql_audit的诊断case

      3.1. 最近100s某个租户的TOP SQL耗时监控

      • 检查语句:
        -- OceanBase 4.0.0.0及以上版本,请替换tenant_name的值为实际的租户名 
        select /*+read_consistency(weak),query_timeout(100000000)*/ SQL_ID,count(1),avg(ELAPSED_TIME),avg(EXECUTE_TIME),avg(QUEUE_TIME),avg(AFFECTED_ROWS),avg(GET_PLAN_TIME) 
        from gv$ob_sql_audit  
        where time_to_usec(now(6))-request_time  (time_to_usec(now()) - 1000000)
        and request_time  
         
        

        3.3. 某个时间段请求次数排在 TOP-N 的 SQL

        • 思路:我们首先可以查出某个时间段内数据库中所有 SQL 并按照 sql_id 级别进行聚合,再统计该时间段内每个SQL_ID的 QPS,取出top值。
        • 语句:
          -- OceanBase 4.0.0.0及以上版本,请替换tenant_id的值为实际租户的值
          select SQL_ID, count(*) as QPS, avg(t1.elapsed_time) RT
          from oceanbase.gv$ob_sql_audit t1
          where   tenant_id = 1001       and IS_EXECUTOR_RPC = 0
          and request_time > (time_to_usec(now()) - 10000000)
          and request_time  (time_to_usec(now()) - 10000000)
          and request_time  
           
          

          3.4. 定位所有SQL中消耗CPU最多的sql

          思路:消耗CPU的时间是elapsed_time - queue_time,因为queue_time的过程中是在排队,并不消耗cpu. 排查消耗CPU最多的sql在cpu飙高的场景非常有用

          语句:

          -- OceanBase 4.0.0.0及以上版本,请替换tenant_id的值为实际租户的值
          select sql_id, substr(query_sql, 1, 20) as query_sql, 
                sum(elapsed_time - queue_time) sum_t, count(*) cnt, 
                avg(get_plan_time), avg(execute_time)    
          from oceanbase.gv$ob_sql_audit     
          where   tenant_id = 1001      
                 and request_time > (time_to_usec(now()) - 10000000)     
                 and request_time  (time_to_usec(now()) - 10000000)     
                 and request_time  
           
          

          3.5. 查看SQL的执行是否出现大量请求不合理的使用了远程执行

          思路:sql_audit的PLAN_TYPE字段可以看到该SQL的执行计划类型,

          • plan_type=1 :本地执行计划。性能最好。
          • plan_type=2 : 远程执行计划。
          • plan_type=3 : 分布式执行计划。包含本地执行计划和远程执行计划。

            一般情况下,如果出现远程执行比较多时可能时出现切主或proxy客户端路由不准的情况。

            语句:

            -- OceanBase 4.0.0.0及以上版本,请替换tenant_id的值为实际租户的值
            select count(*), plan_type    
            from oceanbase.gv$ob_sql_audit     
            where tenant_id = 1001          
                  and IS_EXECUTOR_RPC = 0          
                  and request_time > (time_to_usec(now()) - 10000000)         
                  and request_time  (time_to_usec(now()) - 10000000)         
                  and request_time  
             
            

            3.6. 查询全表扫描的SQL

            思路:sql_audit的TABLE_SCAN字段是标识语句是否走了全表扫描,=1 表示全表扫描了。可以进一步分析一下SQL是否可以添加索引来防止全表扫描:

            语句:

            -- OceanBase 4.0.0.0及以上版本,请替换tenant_id的值为实际租户的值
            select query_sql 
            from oceanbase.gv$ob_sql_audit 
            where table_scan = 1 and tenant_id = 1001 
            group by sql_id;
            -- OceanBase 4.0.0.0以下版本,请替换tenant_id的值为实际租户的值
            select query_sql 
            from oceanbase.gv$sql_audit 
            where table_scan = 1 and tenant_id = 1001 
            group by sql_id;

            3.7 如何分析RT突然抖动的SQL?

                在线上如果出现RT抖动,但RT并不是持续很高的情况,可以考虑在抖动出现后,立刻将sql audit关闭(alter system set ob_enable_sql_audit = 0),从而确保该抖动的SQL请求在sql audit中存在;然后通过3.3章节的【某个时间段请求次数排在 TOP-N 的 SQL】,分析有异常的SQL。

               如果在sql_audit中找到了对应的RT异常请求,则可以分析该请求在sql audit中记录:

            • 查看retry次数是否很多(RETRY_CNT, 如果次数很多,则是否考虑是否有锁冲突或切主等情况)
            • 查看queue time是不是很大(QUEUE_TIME字段)
            • 查看获取执行计划时间(GET_PLAN_TIME), 如果时间很长,一般会伴随IS_HIT_PLAN = 0, 表示没有命中plan cache)
            • 查看EXECUTE_TIME是否很长,如果很长,则

                   a. 查看是否有很长等待事件耗时

                   b. 查看访问的行数是否很多, 看SSSTORE_READ_ROW_COUNT, MEMSTORE_READ_ROW_COUNT两个字段, 比如大小账号场景可能导致rt抖动。

              第一篇“神医”的修炼秘籍——《OceanBase诊断系列》之一
              第二篇一起走进sql_audit性能视图——《OceanBase诊断系列》之二
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]