8.3 运维工具
DOOBA 性能监控
DOOBA 是 OceanBase 内部的一个运维脚本,使用 Python 语言开发,仅支持 Python 2.7 版本。
项目地址:
GitHub 项目地址:https://github.com/oceanbase/oceanbase/tree/master/script/dooba
Gitee 项目地址:https://gitee.com/oceanbase/oceanbase/blob/master/script/dooba
使用方法
DOOBA 的原理是使用 MySQL 命令连接到 OceanBase 的 SYS 租户里,实时展示租户 SQL 的 QPS(包括 select、update、insert、delete、commit ) 以及相应 SQL 的平均延时(RT)。同时还可以查看各个节点的 SQL 的 QPS 以及 RT 等。
说明
若要使用 DOOBA,您必须安装 MySQL 客户端。建议安装 5.5/5.6/5.7 版本的 MySQL 客户端,因为早期的 ODP (版本低于 2.0.0)可能不完全兼容 MySQL 8.0 的连接协议。
使用命令如下:
python dooba.py -h <ODP_IP> -u root@sys#集群名 -P <ODP_PORT> -p <PASSWORD> # 如: python dooba.py -h 172.20.249.54 -u root@sys#obce-3zones -P 2883 -pxxxxxx
登录后常用的快捷键如下:
c:选择租户。一般是观察业务租户的性能。1:查看快捷键。这里没有提到的快捷键尽量别用,不保证功能正确。2:查看租户性能概览。3:查看租户各个节点的性能概览。如果节点很多会显示不全(除非屏幕非常大)。tab:在各个widget之间跳转。d:删除tab焦点所在的widget。R:恢复当前界面所有的widget布局(包括被删除的)。
脚本 dooba 的源码可以直接编辑查看,工具中各个缩写对应的含义都可在源码中找到解释。
租户性能概览
主要查看租户层面 SQL 的 QPS、RT 以及内存、IO 等实时信息。
DOOBA 的性能数据取自 sys 租户的内部视图 gv$sysstat。
DOOBA 的监控信息 SQL 都可以直接查看,可以参考它做类似的监控产品。
# 取 QPS 和 RT 信息 SELECT t1.con_id tenant_id,t2.zone, t1.svr_ip,t1.svr_port , t1.stat_id, t1.name, t1.value FROM gv$sysstat t1 JOIN __all_server t2 ON (t1.svr_ip=t2.svr_ip and t1.svr_port=t2.svr_port) JOIN __all_resource_pool t3 ON (t1.con_id=t3.tenant_id) JOIN __all_unit_config t4 ON (t3.unit_config_id=t4.unit_config_id) WHERE t1.con_id IN (1001) and stat_id in (10000,10004,10005,10006,30007,30008,30009,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,60000,60002,60003,60005,130000,130001,130002,130004) ORDER BY t1.con_id, t2.zone, t1.svr_ip, t1.svr_port;
上述 SQL 可以取出所有节点的性能数据,汇总就是整个租户的性能数据。
需要关注以下几点:
SQL COUNT:QPS 信息。包括各类 SQL 的每秒执行次数。SQL 类型分别是
select、insert、update、delete、replace、commit和rollback。前四类 SQL 总数跟commit的比值大致可以推出事务的平均语句数。rollback是回滚的信息,如果太高,很有可能是数据库有问题或者业务设计有问题。SQL RT:SQL 每次平均执行耗时。包括各类 SQL 的每次平均执行耗时,单位是毫秒(ms)。SQL 类型分别是
select、insert、update、delete、replace、commit。前四类可以看出 SQL 正常情况下的执行耗时水平。如果有大幅变动,可能是因为数据量突增、SQL 缺乏索引、有锁等待、CPU 瓶颈等引起的。具体分析还要结合 SQL 审计视图gv$sql_audit验证。commit的平均执行耗时也可以反映事务的大小。OceanBase 的commit会同步事务所有的事务日志(clog)到多数派节点(包括自身),这个时间会反映在commit的耗时里。如果这个值突然增长很大,说明可能有突发的大事务。当节点网络性能下降时或者时间同步误差变大时,都可能导致commit耗时增大。RPC:反馈网络信息。Memory:MemStore 内存的实时监控。默认情况下,租户可用内存的一半用于 MemStore 的内存,用来存放业务写操作带来的变化的数据。OceanBase 的特色之一就是只写数据的变化部分,并且数据会尽可能的维持在内存里不落盘,直到增量内存利用率到达阈值(参数
freeze_trigger_percentage)后触发转储或合并才将数据落盘并释放内存。转储是内存中增量数据直接写到磁盘暂存,合并是内存中增量数据跟磁盘中基线数据在内存中合并为最新的数据块(SSTable)再写回到数据文件中。转储类似传统数据库的
checkpoint,对租户性能影响很小并且可以调优,合并对租户性能稍大一些并且也是可以调优的。通常建议尽量发起转储,在凌晨低峰期时再发起合并操作。合并可以定时触发,也可以手动触发。当转储次数(参数
minor_freeze_times)用尽时也会自动触发合并。这个监控看的就是增量内存的变化量、累积量和增量内存使用水位。这个监控结果再结合视图
gv$memstore基本上可以定位所有的增量内存不足问题。当这个内存水位增长到freeze_trigger_percentage就会触发转储,当水位继续增长到租户限速阈值(租户参数writing_throttling_trigger_percentage)会触发租户写入限速,当水位增长到接近 100% 的时候,租户内存耗尽,业务写会大量报错(Over tenant memory limit1)。调优参数
freeze_trigger_percentage和转储内部并发数可以将租户的内存水位控制在一个合理的安全的范围内。IOPS:磁盘 IO 的实时监控。SESS是会话数(仅供参考,量大的时候可能会不准)。IOR是读 IOPS,IOR-SZ是读 IO 吞吐量。当第一次读入数据或者数据不在内存中时就会有读物理 IO。读物理 IO 如果非常高,会导致 SQL 的平均延时水平很高,说明内存不足,对 IO 依赖性变大。很可能导致 IO 触达瓶颈。IOW是写 IOPS,IOW-SZ是写吞吐量。平时很少有写 IO,因为 OceanBase 的写都在内存里。只有转储和合并的时候,能看到短暂密集的写 IO。
租户节点性能概览
查看租户在各个节点 SQL 的 QPS、RT 以及一些缓存命中率等。
# 取节点 CPU SELECT t1.con_id tenant_id,t2.zone, t1.svr_ip,t1.svr_port , round(t1.value/(100*t4.max_cpu), 3) cpu_usage FROM gv$sysstat t1 JOIN __all_server t2 ON (t1.svr_ip=t2.svr_ip and t1.svr_port=t2.svr_port) JOIN __all_resource_pool t3 ON (t1.con_id=t3.tenant_id) JOIN __all_unit_config t4 ON (t3.unit_config_id=t4.unit_config_id) WHERE t1.con_id IN (1001) and t1.stat_id=140006 ORDER BY t1.con_id, t2.zone, t1.svr_ip, t1.svr_port;
需要关注以下几点:
活跃会话数:仅供参考,非严格精准。
CPU 利用率:这个是 OceanBase 内部统计的各个节点的 CPU 利用率,不是 OS 里看到的 CPU 利用率(OceanBase 是单进程软件)。
各个缓存的命中率:这里有
Cache Block以及其Cache Block Index的缓存命中率,主要关注前者。理想情况是 99% 或者 100%。当初次读入大量数据、内存有瓶颈或合并后时,这个利用率会低于 99%,甚至低于 90%。如果长期低于 80%,那说明内存瓶颈问题很严重。其他行缓存命中率通常不是问题。物理 IO 读写:各个节点的物理 IO 信息,有很大参考意义。
SQL 的 QPS 以及 RT 信息:各个节点的 QPS 可以看出租户请求在各个节点的流量比例关系,相应的 RT 可以看出各个节点的性能状况。其中最后两个
SLC和SRC表示是节点上的本地 SQL 和远程 SQL 执行次数信息。通常本地 SQL 的性能会比远程 SQL 性能好,所以请注意远程 SQL 的比例,如果比例很高,这个节点的 CPU利用率、SQL 的 RT 均值都会比较高。这个就需要分析原因。可能是租户 PRIMARY_ZONE 不适合打散或者表结构设计不合理,可以考虑使用表分组、调整 PRIMARY_ZONE 或 UNIT_NUM 等等。
ob_admin 工具
ob_admin 是 OceanBase 内部开发和运维使用的一个工具,用于处理一些疑难问题。这个工具不是标准产品,有很大的使用风险。仅供对 OceanBase 原理非常熟悉的技术人员使用。
项目地址:
GitHub 项目地址:https://github.com/oceanbase/oceanbase/tree/master/tools/ob_admin
Gitee 项目地址:https://gitee.com/oceanbase/oceanbase/tree/master/tools/ob_admin
目前 ob_admin 可以用于两个场景:
测试数据盘性能,生成 IO 配置文件。
多数派故障时将单副本强制激活为主副本。
ob_error 工具
ob_error 是随着 OceanBase 一起开源的工具。
项目地址:
GitHub 项目地址:https://github.com/oceanbase/oceanbase/tree/master/tools/ob_error
Gitee 项目地址:https://gitee.com/oceanbase/oceanbase/tree/master/tools/ob_error
ob_error 主要用来查看 OceanBase 错误码含义,节省查文档时间。
[root@obce00 ~]# ./ob_error 4030
OceanBase:
OceanBase Error Code: OB_TENANT_OUT_OF_MEM(-4030)
Message: Over tenant memory limits
Cause: Internal Error
Solution: Contact OceanBase Support
[root@obce00 ~]# ./ob_error 4013
OceanBase:
OceanBase Error Code: OB_ALLOCATE_MEMORY_FAILED(-4013)
Message: No memory or reach tenant memory limit
Cause: Internal Error
Solution: Contact OceanBase Support
Oracle:
Oracle Error Code: ORA-04013
Message: number to CACHE must be less than one cycle
Related OceanBase Error Code:
OB_ERR_SEQ_CACHE_TOO_LARGE(-4328) Addr2line 工具
Addr2line 工具(标准的 GNU Binutils 中的一部分)是一个可以将指令地址和可执行映像转换成文件名、函数名和源代码行数的工具。一般适用于 debug 版本或带有 symbol 信息的库。
命令使用方法:addr2line -pCfe $observer $symbol_addr。其中,$observer 是进程 observer 的目录,$symbol_addr 是进程运行日志中打印的十六进制字符串。
示例如下:
[admin@obce01 oceanbase-ce]$ grep ERROR log/observer.log -A1 [2021-10-08 15:35:14.343634] ERROR easy_client_dispatch (easy_client.c:30) [90761][8][YB42AC14F934-0005CDD26B1C3D3A] [lt=0] [dc=0] easy_io_dispatch is failure: easy not started BACKTRACE:0x9124b6e 0x9060f71 0x9057dcf 0x905abd4 0x92ff0d5 0x9395b48 0x9395cf3 0x930a68e 0x4397e89 0x936beea 0x246f0a5 0x
输出结果是函数的调用关系和参数值。将这些反馈给 OceanBase 技术支持人员,可协助解决问题。
[admin@obce01 oceanbase-ce]$ addr2line -pCfe bin/observer 0x9124b6e 0x9060f71 0x9057dcf 0x905abd4 0x92ff0d5 0x9395b48 0x9395cf3 0x930a68e 0x4397e89 0x936beea 0x246f0a5 0x oceanbase::common::lbt() at ??:? oceanbase::common::ObLogger::check_error_log(oceanbase::common::ObPLogItem&) at ??:? oceanbase::common::ObLogger::async_log_message_kv(char const*, int, oceanbase::common::ObLogger::LogLocation const&, unsigned long, char const*, long) at ??:? oceanbase::common::ObLogger::log_message_va(char const*, int, char const*, int, char const*, unsigned long, char const*, __va_list_tag*) at ??:? oceanbase::common::easy_log_format_adaptor(int, char const*, int, char const*, unsigned long, char const*, ...) at ??:? easy_client_dispatch at ??:? easy_client_send at ??:? oceanbase::rpc::frame::ObReqTransport::send_session(easy_session_t*) const at ??:? int oceanbase::rpc::frame::ObReqTransport::send<oceanbase::obrpc::ObRpcPacket>(oceanbase::rpc::frame::ObReqTransport::Request<oceanbase::obrpc::ObRpcPacket> const&, oceanbase::rpc::frame::ObReqTransport::Result<oceanbase::obrpc::ObRpcPacket>&) const at ??:? oceanbase::obrpc::ObRpcProxy::send_request(oceanbase::rpc::frame::ObReqTransport::Request<oceanbase::obrpc::ObRpcPacket> const&, oceanbase::rpc::frame::ObReqTransport::Result<oceanbase::obrpc::ObRpcPacket>&) const at ??:? int oceanbase::obrpc::ObRpcProxy::rpc_call<oceanbase::obrpc::ObFetchAliveServerArg, oceanbase::obrpc::ObFetchAliveServerResult>(oceanbase::obrpc::ObRpcPacketCode, oceanbase::obrpc::ObFetchAliveServerArg const&, oceanbase::obrpc::ObFetchAliveServerResult&, oceanbase::obrpc::Handle*, oceanbase::obrpc::ObRpcOpts const&) at ??:? ?? ??:0




