百丽时尚 DBA:加入 obdiagSIG 后,运维工作更顺利了17认证网

正规官方授权
更专业・更权威

百丽时尚 DBA:加入 obdiagSIG 后,运维工作更顺利了

本文作者是百丽时尚身处运维一线的 DBA,同也加入了 OceanBase 敏捷诊断工具 obdiag 特别兴趣小组(obdiag SIG),参与功能共建研发。本文主要分享了作者在百丽时尚应用 OceanBase 的过程中,在 obdiag SIG 中的成果与收获,同时也和大家分享了如何利用【obdiag SIG 成员】这一角色解决生产环境的问题。

obdiag 在百丽的应用情况
百丽时尚集团是中国一家大型时尚鞋服集团,连续多年蝉联“中国时尚零售与消费百强榜”前列。在百丽的运营中,从商品趋势研究到设计研发、零售,再到客户运营,数字化技术渗透进业务的每个细胞。此前业务系统使用 MySQL+MyCAT 的分库分表架构,并使用 orchestrator 作为高可用的管理中间件。由于 MyCAT架构不支持分布式事务,同时存在分片业务调整困难、可扩展性差等问题,2023 年,百丽将业务系统迁移至OceanBase 4.2.1 版本。OceanBase 是一款原生分布式数据库,在分布式查询优化、水平可扩展性和周边工具生态方面表现优异,能够精准解决百丽之前的痛点,减少运维复杂度,从而降低运维成本。自上线以来,在 OceanBase 数据库在百丽技术团队内部深受欢迎。目前,OceanBase 已成功上线订单中心和消息中心两大核心业务,并平稳运行。作为一线 DBA,我们在日常的信息收集、集群巡检、SQL 诊断和问题根因分析等多个场景中都使用到了 OceanBase 的诊断工具 obdiag。obdiag 是一款适用于黑屏的诊断工具,现有功能包含了对 OceanBase 日志、SQL Audit 以及 OceanBase 进程堆栈等信息进行的扫描、收集,可以在 OceanBase 集群不同的部署模式下实现一键执行,完成诊断信息的获取。obdiag 帮助我们省略了此前遇到问题寻求官方支持时繁琐的信息收集动作和复杂的流程,也加快了问题诊断的效率。

我眼中的 obdiag
作为 obdiag 的使用者和共建者,下面我从两个视角阐述 obdiag 带给我的收获,以及如何更好地利用 obdiag 解决问题。(一)运维者视角的 obdiag
站在运维视角,有两种使用 obdiag 的方式。首先以典型的实时锁冲突场景为例。下面有两个会话,它们都是做同一操作,即对一张表的一条数据做 select for update 操作。我们在会话一先执行,当会话二在做相同动作时就会等待。面对上述场景,我们只需使用 obdiag 执行一条命令:obdiag rca run –scene=lock_conflict,即可一键分析出我们持有的会话及其事务 ID,接着自动给出解决建议。

  • cat obdiag_lock_conflict_20240808175840/record
  • +------------------------------------------------------------------------------------------------------------------------------------------+| record |+------+-----------------------------------------------------------------------------------------------------------------------------------+| step | info | +------+-----------------------------------------------------------------------------------------------------------------------------------+| 1 | by select * from oceanbase.GV$OB_LOCKS where BLOCK=1; the len is 2 | | 2 | get holding_lock trans_id:31794294 | | 3 | get holding_lock_session_id:3222014434 || 4 | wait_lock_trans_id is 31794336 || 5 | get wait_lock_session_id:3222015259 | | 6 | exec sql: SELECT * FROM oceanbase.gv$OB_SQL_AUDIT where SID="3222014434"; to get || | holding_lock_sql_info. | | 7 | holding_lock_session_id: 3222014434; not find sql_info on gv$OB_SQL_AUDIT | +------+-----------------------------------------------------------------------------------------------------------------------------------+
  • The suggest: holding_lock_session_id: 3222014434; wait_lock_session_id : 3222015259, sql_info: not find. Lock conflicts can be ended by killing holding_lock_session_id or wait_lock_session_id

其次,以典型的历史锁冲突场景为例。当发生锁冲突我们没来得及执行分析命令或当下不知道执行什么命令,希望找到历史锁冲突时,有两种方法:

👉 第一种方法:通过 OCP,会发现响应时间远远大于执行时间。

👉 第二种方式:通过 GV$OB_SQL_AUDIT: 命令,可以看到响应时间。

  • QUERY_SQL:select * from config where config_name = 'test rule' for update;REQUEST_TIME:1723187738073566ELAPSED_TIME:4513197NET_TIME:0NET_WAIT_TIME:0QUEUE_TIME:0DECODE_TIME:0GET_PLAN_TIME:103964EXECUTE_TIME:43923RETRY_CNT:3403

如果响应时间大于执行时间,往往会有多次重复执行,那么结合重复次数就可以判断是否发生了锁冲突。

接下来我们使用 obdiag 收集日志:

  • obdiag gather log --from='2024-08-09 15:10:00' --to='2024-08-09 15:30:00' --grep="ret=-6004"

从日志中筛选和锁冲突相关的错误代码,比如 6003/6004/6005,从日志中找到代码。

  • [2024-08-0915:20:52.514054]WDIAG[STORAGE.TRANS]inner_lock_for_read(ob_tx_data_functor.cpp:290)[279073][T1006_TenantInf][T1005][YB420AFA0270-0006196BA9DFF148-0-0][lt=4][errcode=-6004]lock_for_readneedretry(ret=-6004,tx_data={tx_id:{txid:325843478},ref_cnt:1,state:"RUNNING",commit_version:{val:1723188052513540049,v:0},start_scn:{val:1723188052513540049,v:0},end_scn:{val:18446744073709551615,v:3}

这些代码意味着集群中出现过历史锁冲突,如此便可以快速定位历史问题。

最后一个例子是 obdiagSQL 优化。假设 test1 和 test2 是结构完全相同的两张表,但 test2 的数据量远大于 test1。连接条件为 t1.c1=t2.c1:

  • create table test1 (c1 int primary key, c2 int, key t1_i1(c2) local) partition by hash(c1) partitions15;create table test2 (c1 int primary key, c2 int, key t2_i1(c2) local) partition by hash(c1) partitions15;explain select * from test1 t1, test2 t2 where t1.c1 = t2.c1 and t1.c2 > 1 and t1.c2 < 1000;====================================================================== || |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | ---------------------------------------------------------------------- |0 |PX COORDINATOR | |89 |484 | |1 |└─EXCHANGE OUT DISTR |:EX10001 |89 |416 | |2 | └─HASH JOIN | |89 |264 | |3 | ├─EXCHANGE IN DISTR | |89 |172 | |4 | │ └─EXCHANGE OUT DISTR (PKEY) |:EX10000 |89 |138 | |5 | │ └─PX PARTITION ITERATOR | |89 |62 | |6 | │ └─TABLE RANGE SCAN |t1(t1_i1)|89 |62 | |7 | └─PX PARTITION ITERATOR | |100 |63 | |8 | └─TABLE FULL SCAN |t2 |100 |63 | ====================================================================== |

在执行计划中,会对 test2 做全表扫描,但这不是我们想要的,这时,我们就可以通过 obdiag 命令去收集执行计划。

  • obdiag gather plan_monitor --trace_id=TRACE_ID --env="{db_connect='-h127.0.0.1 -P2881 -utest@test -p****** -Dtest'}"

从收集结果中可以发现,test2 的估行和吐行差距过大,统计信息有问题。

  • call dbms_stats.gather_table_stats('test', 'test2');

通过 obdiag 重新统一信息,就可以解决问题。obdiag 简单易用,帮助我们解决了很多问题,运维效率不断提升。因此,我也希望投入更多精力,为 obdiag 做一些贡献。

(二)开发者视角的 obdiag

OceanBase 的敏捷诊断工具兴趣小组,即 obdiagSIG,是一个建设并推广 obdiag 工具及生态的开源小组,目标是打造一个集用户体验卓越、功能强大、社群活跃于一体的 OceanBase 诊断生态系统。

在参与共建的过程中,我发现了很多与用户运维视角不一样的东西。例如 obdiag rca 锁冲突场景,对于使用者而言,有时无法采集到导致锁冲突的会话 ID,而在开发者视角,发现导致这个问题出现的根本原因在于,obdiag 是通过 gv$ob_lock的trans_id 和  gv$ob_transaction_participants 关联获取 tx_id,然后关联 gv$ob_transaction_participants,但 gv$ob_transaction_participants 是集群视图会取到多条数据。而用户持有的会话只是连接到后端的一个 OBServer 上,其他的会话 ID 显示为 0,导致用户无法采集到相应结果。

优化逻辑比较简单,快速编辑本地运行目录中根因分析相关的脚本文件:obdiag/rca/lock_conflict_scene.py。只需要加一个条件:计算 ID 不等于零。然后把对应的数据查出来,这时用户想查询的会话 ID 就会显示。

优化后:

  • cat obdiag_lock_conflict_20240808175840/record
  • +------------------------------------------------------------------------------------------------------------------------------------------+| record |+------+-----------------------------------------------------------------------------------------------------------------------------------+| step | info | +------+-----------------------------------------------------------------------------------------------------------------------------------+| 1 | by select * from oceanbase.GV$OB_LOCKS where BLOCK=1; the len is 2 | | 2 | get holding_lock trans_id:31794294 | | 3 | get holding_lock_session_id:0 || 4 | wait_lock_trans_id is 31794336 || 5 | get wait_lock_session_id:3222015259 | | 6 | exec sql: SELECT * FROM oceanbase.gv$OB_SQL_AUDIT where SID="0"; to get || | holding_lock_sql_info. | | 7 | holding_lock_session_id: 3222014434; not find sql_info on gv$OB_SQL_AUDIT | +------+-----------------------------------------------------------------------------------------------------------------------------------+
  • The suggest: holding_lock_session_id: 0; wait_lock_session_id : 3222015259, sql_info: not find. Lock conflicts can be ended by killing holding_lock_session_id or wait_lock_session_id

再比如 obdiag display 功能共建,此前我们在运维过程中需要用到大量的 SQL 及命令,这些 SQL 和命令管理起来非常麻烦,往往都会记录在自己的“小本本”上,需要用到的时候再去翻找对应命令,而经验不足的用户在方面可能会无从下手。

因此,我们借助 OceanBase 官方的能力,将常用的一些命令和 SQL 集成到 obdiag 中,只需要一条命令,快速响应并展示结果,降低运维的难度,让小白用户也能像老鸟一样在 OceanBase 的海洋中遨游。

obdiag SIG 共建经验及感受
很多用户和最初的我一样,认为参与共建会不会耽误自己的本职工作,或者对研发能力要求很高,担心自己无法胜任会遭受打击。但其实,参与 OceanBase 的共建非常简单,比如我们增加一个场景,只需打开运行目录对应模块下的配置文件,根据规则和步骤创建即可。例如:

  • #展示场景增加vi~/.obdiag/display/task/observer/demo.yaml:info_en:"[test]"info_cn:"[测试case]"task: -version:"[3.1.0,3.2.4]"steps: {steps_object} -version:[4.2.0.0,4.3.0.0]steps: {steps_object}

目前的一些成果展示如下:

目前 obdiag 2.5.0 版本已经正式引入了 obdiag display 功能,也欢迎大家体验和给出指导建议。加入 obdiagSIG 后,不仅没有耽误我的本职工作,还让我的运维工作更加顺利。这一切都源于自己在运维过程中,需要经常采集信息通过社区论坛等形式反馈给 OceanBase 官方,随着收集信息越来越多,收集频率越来越高,我开始接触 obdiag。同时,我们利用 obdiag 解决生产问题的次数也越来越多,我开始对 obdiag 强大的 DIY 功能吸引,可以很便捷的把自己想要的功能植入 obdiag,在共建的工程中也进一步加深了对 obdiag 的理解。作为 OceanBase 的用户和 obdiag 的共建者,我真心希望更多的一线运维人员和开发者可以参与 obdiag 项目,集思广益、群策群力,建设更加完善的 obdiag 场景以及更加强大的 obdiag 知识库,更好地解决我们在运维过程中遇到的问题。感兴趣可以添加 OB 小助手(OBCE666),发送 obdiagSIG 入群即可加入。

想了解更多干货,可通过下方扫码关注

详情咨询

可扫码添加上智启元官方客服微信👇

未经允许不得转载:17认证网 » 百丽时尚 DBA:加入 obdiagSIG 后,运维工作更顺利了
分享到:0

评论已关闭。

400-663-6632
咨询老师
咨询老师
咨询老师