ob锁问题如何排查

【 使用环境 】 测试环境
【 OB or 其他组件 】
【 使用版本 】OB V4.2.1
【问题描述】OBV4版本锁如何进行排查,在 select * from gv$ob_locks中如果 BLOCK 为 1,如何排查阻塞源

@论坛小助手

在OceanBase V4.2.1中排查锁问题,特别是当select * from gv$ob_locks查询结果中BLOCK为1时,表示存在阻塞源。您可以参考以下步骤进行排查:

  1. 查看死锁记录

    SELECT * FROM oceanbase.cdb_ob_deadlock_event_history ORDER BY create_time DESC LIMIT 10;
    

    其中 role=victim 表示被杀掉的事务。

  2. 查看事务相关SQL

    SELECT usec_to_time(REQUEST_TIME), TRACE_ID, TX_ID, QUERY_SQL FROM gv$ob_sql_audit WHERE TX_ID=<阻塞事务ID> ORDER BY REQUEST_TIME;
    

    如果没有开启SQL Audit功能,可以查看 enable_sql_audit 配置项是否设置为True:

    show parameters where name = 'enable_sql_audit';
    

    如果查询结果为False,则看不到事务对应的SQL命令,需要通过日志筛选事务ID。

  3. 查询SQL对应日志
    查到事务相关SQL后,用发生冲突的那条SQL的Trace ID,在日志里面搜索:

    grep '<trace id>' observer.log*
    

    可以看到该条SQL的所有日志,一般最后一条包含报给客户端的错误码。

  4. 调整日志级别和带宽限制
    如果没有日志,说明日志级别不对或日志限流了。可以将日志级别调成 WDIAG,日志带宽限制调大:

    alter system set syslog_level='WDIAG';
    alter system set syslog_io_bandwidth_limit='2G';
    
  5. 其他锁相关错误码

    • 表锁相关,上锁时发生锁冲突(错误码从 V4.0.0 版本开始引入):
      * 错误原因:表锁相关,上锁时发生锁冲突。
      * 解决方法:预留错误码,暂未启用。
      
    • 表锁相关,锁表中对应锁不存在(错误码从 V4.0.0 版本开始引入):
      * 错误原因:表锁相关,锁表中对应锁不存在。
      * 解决方法:内部错误码。请联系技术人员协助排查。
      
    • 表锁相关,上锁时对应的锁操作已经存在,即重复上锁(错误码从 V4.0.0 版本开始引入):
      * 错误原因:表锁相关,上锁时对应的锁操作已经存在,即重复上锁。
      * 解决方法:内部错误码。请联系技术人员协助排查。
      

具体信息可参考以下文档:

  1. OceanBase Sysbench 高性能部署和问题分析
  2. 6000 ~ 6999

select
ls.tenant_id,
plist.tenant,
plist.user,
plist.db,
(
select
concat(table_name, ‘-’, table_id)
from
oceanbase.CDB_OB_TABLE_LOCATIONS t
where
t.tablet_id = ls.tablet_id
and t.tenant_id = ls.tenant_id
and t.role = ‘LEADER’
) as tableinfo,
plist1.time LOCK_TIME,
plist1.total_time LOCK_TOTAL_TIME,
plist.time WAIT_TIME,
plist.total_time WAIT_TOTAL_TIME,
plist.user_client_ip WAIT_USER_CLIENTIP,
plist.retry_cnt,
plist1.id LOCK_SID,
plist.id WAIT_SID,
plist1.svr_ip LOCK_SVRIP,
plist.svr_ip WAIT_SVRIP,
ls.holder_trans_id LOCK_TRANS,
plist.trans_id WAIT_TRANS,
ls.rowkey,
usec_to_time(ls.recv_ts),
usec_to_time(ls.lock_ts),
ls.try_lock_times,
plist1.PROXY_SESSID,
plist.PROXY_SESSID,
plist1.host,
plist.host
from
oceanbase.GV$OB_PROCESSLIST plist
LEFT JOIN oceanbase.__ALL_VIRTUAL_LOCK_WAIT_STAT ls ON (plist.id = ls.session_id and plist.trans_id = ls.trans_id and plist.svr_ip = ls.svr_ip)
LEFT JOIN oceanbase.GV$OB_PROCESSLIST plist1 ON ls.holder_trans_id = plist1.trans_id
where
plist.retry_info = ‘-6005’;

找到锁表所在的LEADER通过过滤observer的日志也可以找出锁的源头egrep “ob_data_access_service.cpp” observer.log|awk -F " " ‘{delete sn;rst="";for(i=1;i<=NF;i++){if(!sn[$i]++){if(i~/^(1|2|7)$/||$i~/^data_table/||$i ~/^tx_id:{txid:/||$i ~/^cflict_txs/||$i~/^addr/||$i~/^scheduler_addr/){rst=rst $i " “;}}} gsub(/,|:[{tx_id|data_table:{|}]/,”",rst);print rst;}’

一行式检查OceanBase 4.x锁信息 - 社区问答- OceanBase社区-分布式数据库
可以参考下这个,在421版本测试,可以找到对应的锁阻塞语句,

425版本测试可以通过如下语句找到阻塞以及被阻塞信息
cat observer.log.20260129060442242|perl -nle ‘if(/([^]]+?]).([YB.?]).mvcc write conflict.(tx_id={txid:\d+}).(lock_trans_id:{txid:\d+})/){$a=$1;$b=$2;$c=$3;$d=$4};if(/ob_data_access_service.cpp/&& /6005/ && /\Q$b\E/){if(/ob_data_access_service.?(tenant_id:\d+).?(session_id:\d+).?(holder_sess_id:\d+).?(tablet_id:{id:\d+}).?(ls_id:{id:\d+}).*?data_table:{(table_id:\d+),\s+schema_version:\d+,\s+table_type:3/){$h=$1;$j=$2;$k=$4;$l=$3;$q=$5;$e=$6;print “$a $b $c $d $h $j $l $k $q $e”}}’