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

记一次 OB 自证清白之旅

51
本文是一篇新鲜的严肃的 OB 技术问题分析案例,请勿想歪。

昨晚快 10 点时,接一客户 OB 社区版使用问题咨询,让帮查一下中午12点多业务一次请求异常原因。远程连接客户桌面登录到 OCP 平台后我习惯性的先花几分钟看看客户 OB 的异常告警。结果发现有大量 SQL巡检:性能下降的告警。心里想不会这么巧吧。我刚写完《OB SQL 性能抖动问题分析和应对》文章,就又让我看到这个问题。客户提醒我是看中午12点到1点之间的,于是查看历史告警信息,也发现有同样的告警,尽管每次告警在1个小时后自己恢复了。
于是我提醒客户这个实例有很多慢SQL问题需要 关注,结果客户说这些慢SQL是历史遗留问题,不是他想要的东西。他想看12点多到 1 点应用一个请求耗时达 3 分钟的原因。于是给我看了一下应用的一个日志,非常简单某个时刻应用发起一次请求记录了一笔日志,然后下一笔就是完成该请求,耗时达160秒左右。
日志的时间点倒是很明确,除此之外没有别的信息。我问这个应用请求是做什么的,发什么 SQL。客户问 OB 能不能根据一个关键词搜索 SQL 执行记录。这不是 OB 最擅长的吗,又撞枪口上了!客户给了一个视图名和视图结构以及该视图的一个查询 SQL( SQL 很简单,后来才明白是个示意用的 SQL,不是真实的 SQL)。于是打开一个数据库客户端查询 OB SQL审计视图(gv$ob_sql_audit)。
后面 SQL 和截图都是为了说明这个问题的内部查询结果(非客户环境)。
    SELECT usec_to_time(request_time) req_time, svr_ip, client_ip, user_client_ip, plan_id, ret_code,sql_id, query_sql, elapsed_time,execute_time,event
    FROM oceanbase.gv$ob_sql_audit
    WHERE query_sql LIKE '%bmsql_oorder%'
    AND request_time BETWEEN time_to_usec('2024-07-04 12:15:00') AND time_to_usec('2024-07-04 13:00:00')
    ORDER BY request_time DESC LIMIT 100;
    复制

    结果没有记录返回。显然客户业务还是有一定量(QPS),晚上查中午的 SQL 全量记录已经被淘汰掉了。这个也很常见。

    理论上 OCP 也会采集这个 OB 的 SQL 全量记录。通过 OCP 查询租户在那个时间点的 那个关键字的 TOP SQL。

    不过得到的确实很多按 SQL 汇总的信息,不是单条 SQL 的执行记录。这也不是办法。

    下一步转而想去查 OBProxy 的日志。于是询问客户应用连接的数据库 IP,并确认这个 IP 是不是负载均衡的 VIP。果然应用并不是直连 OBProxy,而是在三个 OBProxy 之前加了一个 类似 nginx 反向代理。于是搜索所有 OBProxy 在那个时间段的慢日志、诊断日志和报错日志。心里想既然是问题 SQL,执行时间肯定很长甚至报错。

    结果所有 OBProxy 都没有记录。再次跟客户沟通其目的,并确认关键词是否正确。


    于是客户发起电话语音再次解释了一下其目的是要查询 12点26分左右一次业务请求耗时 3 分钟的原因,是不是跟 OB 有关。客户再次描述了一下业务到数据库的链路。大体意思是应用会连接到一个应用中间件,应用中间件连接反向代理,反向代理到 OBProxy。应用中间件里日志显示该次请求耗时约 160秒。客户分析反向代理日志没有什么发现,所以就想确认是不是 OB 出了问题。

    于是我明白了客户之所以晚上 10 点多还在查一个中午 12 点的请求问题的重要性。再次询问了请求的细节内容。客户又展示了一段日志,从里面能看到应用发的 SQL条件中具体的值(可能是某个名字,这里示例为 O35Ysg8I5T )。于是再次查询 OBProxy 的慢日志、摘要日志和报错日志。还是没有。我都有点怀疑这个 SQL 有没有跑过,后来想到加一下 OBProxy.log 日志,这里面也有全部的 SQL 信息。一查询果然定位到数笔记录。客户一眼就找出了那个时间点的日志。

    于是客户问这个日志里的时间是 SQL 开始执行的时间还是 SQL 执行结束时的时间。这个应该是开始执行 SQL 时时间,不过为了更严谨的说明问题,我打算把这个连接的所有日志都查询出来。根据图中日志的 csid=1572971 这个信息,登录这个 OBProxy 查这个客户端会话(其实 OCP 里也可以查询)。

      [admin@server062 log]$ cat obproxy.log |grep cs_id |grep 1572971
      [2024-07-05 06:31:49.365515] INFO [PROXY.CS] ob_mysql_client_session.cpp:370 [36465][Y0-00007F2336567360] [lt=16] [dc=0] client session born(cs_id=1572971, proxy_sessid=0, is_local_connection=false, client_vc=0x7f233655fa80, client_fd=80, client_addr="10.0.0.65:21858")
      [2024-07-05 06:31:49.365538] INFO [PROXY.CS] ob_mysql_client_session.cpp:241 [36465][Y0-00007F2336567360] [lt=10] [dc=0] Starting new transaction using sm(cs_id=1572971, get_transact_count()=0, sm_id=296)
      [2024-07-05 06:31:49.366539] INFO [PROXY.SS] ob_mysql_server_session.cpp:106 [36465][Y0-00007F2336567360] [lt=6] [dc=0] server session born(ss_id=41, server_ip={10.0.0.62:2881}, cs_id=1572971, proxy_sessid=0, server_type=1)
      [2024-07-05 06:31:49.366598] INFO [PROXY.TXN] ob_mysql_transact.cpp:4736 [36465][Y0-00007F2336567360] [lt=13] [dc=0] succ to set proxy_sessid(cs_id=1572971, proxy_sessid=720576206856192010, server_ip={10.0.0.62:2881}, ss_id=41, server_sessid=3221697167, is_proxy_mysql_client=false, ss_fd=83, client_addr="10.0.0.65:21858")
      [2024-07-05 06:33:21.121272] INFO [PROXY.TXN] ob_mysql_transact.cpp:364 [36465][Y0-00007F2336567360] [lt=4] [dc=0] user first dml got(cs_id=1572971, sql=select * from bmsql_warehouse where w_name='O35Ysg8I5T')
      [2024-07-05 06:33:23.704394] INFO [PROXY.SS] ob_mysql_server_session.cpp:153 [36465][Y0-00007F2336567360] [lt=30] [dc=0] server session do_io_close((*this={ss_id:41, server_sessid:3221697167, server_ip:{10.0.0.62:2881}, is_inited:true, magic:19136237, state:1, server_vc:0x7f2332acdbd0, client_session:{this:0x7f2336f511c0, is_proxy_mysql_client:false, is_waiting_trans_first_request:false, need_delete_cluster:false, is_first_dml_sql_got:true, vc_ready_killed:false, active:true, magic:19132429, conn_decrease:true, current_tid:36465, cs_id:1572971, proxy_sessid:720576206856192010, session_info:{is_inited:true, priv_info:{has_all_privilege:false, cs_id:1572971, user_priv_set:133009965054, cluster_name:"OB4216", tenant_name:"obmysql", user_name:"root"}, version:{common_hot_sys_var_version:0, common_sys_var_version:0, mysql_hot_sys_var_version:0, mysql_sys_var_version:0, hot_sys_var_version:1, sys_var_version:9, user_var_version:1, db_name_version:1, last_insert_id_version:0, sess_info_version:2}, hash_version:{common_hot_sys_var_version:0, common_sys_var_version:0, mysql_hot_sys_var_version:0, mysql_sys_var_version:0, hot_sys_var_version:0, sys_var_version:0, user_var_version:0, db_name_version:0, last_insert_id_version:0, sess_info_version:0}, val_hash:{common_hot_sys_var_hash:0, common_cold_sys_var_hash:0, mysql_hot_sys_var_hash:0, mysql_cold_sys_var_hash:0, hot_sys_var_hash:0, cold_sys_var_hash:0, user_var_hash:0}, global_vars_version:0, is_global_vars_changed:false, is_trans_specified:false, is_user_idc_name_set:false, is_read_consistency_set:false, idc_name:"", cluster_id:0, real_meta_cluster_name:"", safe_read_snapshot:1, syncing_safe_read_snapshot:0, route_policy:1, proxy_route_policy:3, user_identity:0, global_vars_version:0, is_read_only_user:false, is_request_follower_user:false, obproxy_force_parallel_query_dop:1, ob20_request:{remain_payload_len:0, ob20_request_received_done:false, ob20_header:{ob 20 protocol header:{compressed_len:0, seq:0, non_compressed_len:0}, magic_num:0, header_checksum:0, connection_id:0, request_id:0, pkt_seq:0, payload_len:0, version:0, flag_.flags:0, reserved:0}}, client_cap:0, server_cap:916303, last_server_addr:{*Not IP address [0]*:0}, last_server_sess_id:0, init_sql:""}, dummy_ldc:{use_ldc:false, idc_name:"", item_count:2, site_start_index_array:[[0]0, [1]2, [2]2, [3]2], item_array:[[0]{idc_type:"SAME_IDC", zone_type:"ReadWrite", replica:{server:"10.0.0.63:2881", is_dup_replica:false, role:"FOLLOWER", type:"FULL"}, is_merging:false, is_partition_server:false, is_force_congested:false, is_used:true}, [1]{idc_type:"SAME_IDC", zone_type:"ReadWrite", replica:{server:"10.0.0.62:2881", is_dup_replica:false, role:"FOLLOWER", type:"FULL"}, is_merging:false, is_partition_server:false, is_force_congested:false, is_used:true}], pl:null, ts:0x7f23357a6d00, readonly_exist_status:"READONLY_ZONE_NOT_EXIST"}, dummy_entry:0x7f23391258b0, server_state_version:2, cur_ss:0x7f2332670d70, bound_ss:null, lii_ss:null, cluster_resource:{this:0x7f2335949080, ref_count:26, is_inited:true, cluster_info_key:{cluster_name:{config_string:"OB4216"}, cluster_id:0}, cr_state:"CR_AVAIL", version:2, last_access_time_ns:1720132403703664351, deleting_completed_thread_num:0, fetch_rslist_task_count:0, fetch_idc_list_task_count:0, last_idc_list_refresh_time_ns:1720132157657606744, last_rslist_refresh_time_ns:1720132157638986140, server_state_version:2}, client_vc:0x7f233655fa80, using_ldg:false, trace_stats:NULL}, transact_count:5, server_trans_stat:1, session_info:{cap:916303, ob_server:, version:{common_hot_sys_var_version:0, common_sys_var_version:0, mysql_hot_sys_var_version:0, mysql_sys_var_version:0, hot_sys_var_version:1, sys_var_version:9, user_var_version:1, db_name_version:1, last_insert_id_version:0, sess_info_version:2}, val_hash:{common_hot_sys_var_hash:0, common_cold_sys_var_hash:0, mysql_hot_sys_var_hash:0, mysql_cold_sys_var_hash:0, hot_sys_var_hash:0, cold_sys_var_hash:0, user_var_hash:0}, checksum_switch:1, server_type:1}}, server_vc_=0x7f2332acdbd0, this=0x7f2332670d70)
      [2024-07-05 06:33:23.704600] INFO [PROXY.SS] ob_mysql_server_session.cpp:190 [36465][Y0-00007F2336567360] [lt=200] [dc=0] server session is closing(ss_id=41, server_sessid=3221697167, server_ip={10.0.0.62:2881}, cs_id=1572971, proxy_sessid=720576206856192010)
      [2024-07-05 06:33:23.704622] INFO [PROXY.TXN] ob_mysql_transact.cpp:5781 [36465][Y0-00007F2336567360] [lt=6] [dc=0] [ObMysqlTransact::handle_server_connection_break](client_ip={10.0.0.65:21858}, server_ip={10.0.0.62:2881}, cs_id=1572971, proxy_sessid=720576206856192010, ss_id=0, server_sessid=0, sm_id=296, proxy_user_name=root@obmysql#OB4216, database_name=tpccdb, server_state="INTERNAL_ERROR", request_cmd="Quit", sql_cmd="Quit", sql=)
      [2024-07-05 06:33:23.704642] INFO  [PROXY.SS] ob_mysql_client_session.cpp:652 [36465][Y0-00007F2336567360] [lt=4] [dc=0] client session do_io_close((*this={this:0x7f2336f511c0, is_proxy_mysql_client:false, is_waiting_trans_first_request:false, need_delete_cluster:false, is_first_dml_sql_got:true, vc_ready_killed:false, active:true, magic:19132429, conn_decrease:true, current_tid:36465, cs_id:1572971, proxy_sessid:720576206856192010, session_info:{is_inited:true, priv_info:{has_all_privilege:false, cs_id:1572971, user_priv_set:133009965054, cluster_name:"OB4216", tenant_name:"obmysql", user_name:"root"}, version:{common_hot_sys_var_version:0, common_sys_var_version:0, mysql_hot_sys_var_version:0, mysql_sys_var_version:0, hot_sys_var_version:1, sys_var_version:9, user_var_version:1, db_name_version:1, last_insert_id_version:0, sess_info_version:2}, hash_version:{common_hot_sys_var_version:0, common_sys_var_version:0, mysql_hot_sys_var_version:0, mysql_sys_var_version:0, hot_sys_var_version:0, sys_var_version:0, user_var_version:0, db_name_version:0, last_insert_id_version:0, sess_info_version:0}, val_hash:{common_hot_sys_var_hash:0, common_cold_sys_var_hash:0, mysql_hot_sys_var_hash:0, mysql_cold_sys_var_hash:0, hot_sys_var_hash:0, cold_sys_var_hash:0, user_var_hash:0}, global_vars_version:0, is_global_vars_changed:false, is_trans_specified:false, is_user_idc_name_set:false, is_read_consistency_set:false, idc_name:"", cluster_id:0, real_meta_cluster_name:"", safe_read_snapshot:1, syncing_safe_read_snapshot:0, route_policy:1, proxy_route_policy:3, user_identity:0, global_vars_version:0, is_read_only_user:false, is_request_follower_user:false, obproxy_force_parallel_query_dop:1, ob20_request:{remain_payload_len:0, ob20_request_received_done:false, ob20_header:{ob 20 protocol header:{compressed_len:0, seq:0, non_compressed_len:0}, magic_num:0, header_checksum:0, connection_id:0, request_id:0, pkt_seq:0, payload_len:0, version:0, flag_.flags:0, reserved:0}}, client_cap:0, server_cap:916303, last_server_addr:{*Not IP address [0]*:0}, last_server_sess_id:0, init_sql:""}, dummy_ldc:{use_ldc:false, idc_name:"", item_count:2, site_start_index_array:[[0]0, [1]2, [2]2, [3]2], item_array:[[0]{idc_type:"SAME_IDC", zone_type:"ReadWrite", replica:{server:"10.0.0.63:2881", is_dup_replica:false, role:"FOLLOWER", type:"FULL"}, is_merging:false, is_partition_server:false, is_force_congested:false, is_used:true}, [1]{idc_type:"SAME_IDC", zone_type:"ReadWrite", replica:{server:"10.0.0.62:2881", is_dup_replica:false, role:"FOLLOWER", type:"FULL"}, is_merging:false, is_partition_server:false, is_force_congested:false, is_used:true}], pl:null, ts:0x7f23357a6d00, readonly_exist_status:"READONLY_ZONE_NOT_EXIST"}, dummy_entry:0x7f23391258b0, server_state_version:2, cur_ss:null, bound_ss:null, lii_ss:null, cluster_resource:{this:0x7f2335949080, ref_count:26, is_inited:true, cluster_info_key:{cluster_name:{config_string:"OB4216"}, cluster_id:0}, cr_state:"CR_AVAIL", version:2, last_access_time_ns:1720132403703664351, deleting_completed_thread_num:0, fetch_rslist_task_count:0, fetch_idc_list_task_count:0, last_idc_list_refresh_time_ns:1720132157657606744, last_rslist_refresh_time_ns:1720132157638986140, server_state_version:2}, client_vc:0x7f233655fa80, using_ldg:false, trace_stats:NULL}, client_vc_=0x7f233655fa80, this=0x7f2336f511c0)
      [2024-07-05 06:33:23.704742] INFO [PROXY.CS] ob_mysql_client_session.cpp:94 [36465][Y0-00007F2336567360] [lt=56] [dc=0] client session destroy(cs_id=1572971, proxy_sessid=720576206856192010, client_vc=NULL)
      复制

      这个日志里第一笔记录就是连接建立时间,里面还有个客户端 IP(确认是反向代理服务器的 IP)。根据这个日志时间客户确定了反向代理的请求确实发到了 OBProxy 并且执行成功且不慢。那诡异的 160秒主要是发生在请求到 OBProxy 之前。嫌疑最大的就是反向代理产品。

      至此,真相大白。


      整个问题排查耗时差不多 40 分钟。总结起来有以下几点经验。
      沟通占了一定比例。由于这个客户(还是准客户)平时不怎么沟通,所以我对客户 OB 情况也不了解。排查问题之初先是花了一点时间了解客户 OB 性能状况。如果平时多沟通,持续关注客户 OB 性能情况,那么临时紧急问题排查时可以省去一些不必要的沟通确认。此外就是问题信息要描述准确并提供具体的线索或关键词等。这次问题排查后面能快速有结果得益于一个区分度非常高的关键词。

      此外,OB 运维功夫在平时,连接问题排查(参考文末连接),SQL 性能定位,执行计划分析都是基本功。OB 业务数据库的稳定性和高性能也是需要持续的分析和优化,有问题不处理,小问题变大问题,简单问题变复杂问题,沟通分析处理成本也越大。

      OB 社区版客户如果没有 F5 之类负载均衡设备,往往会借用软负载产品或技术如 SLB、HAProxy、Nginx 反向代理等用于 OBProxy 的高可用。这类产品的成熟度各不相同,需要配置相应的监控和日志,以便有问题时分析。

      OBProxy 的日志信息尽可能保留的久,包括 OBServer 的日志也是同理(上面也查询过 OBServer 日志,没有找到那个关键字,估计日志已经清理了)。OB 产品的日志量非常大,每组日志文件在 260MB 左右,繁忙的业务保留一天的日志可能需要 200G+ 。有些客户总是质疑为什么 home/admin/oceanbase 目录要这么大空间。在日志里省空间,影响就是发生问题要排查的时候容易日志没了。

      得亏这次是 OceanBase 数据库,所有连接和 SQL 都有运行日志,得以自证清白。否则,客户这个问题就说不清楚了。


      更多阅读参考:

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

      评论