适用版本
OceanBase 数据库 V2.x 和 V3.x 版本。
问题描述
业务在 100 并发时,事务提交耗时很长(数百毫秒)。
问题诊断
观察到 Leader 节点网络流量高,CPU 飙升。

搜索 observer 涉及的事务中表的日志,发现存在
transaction log sync use too much的信息,最长耗时达到 980ms。日志存在大量post trans msg error报错,持续在retry 2pc protocol。[2022-09-07 13:47:28.523024] WARN [STORAGE.TRANS] post_2pc_request_ (ob_trans_coord_ctx.cpp:3094) [7850][0][Y9C400B9E367C-0005E79A8AFD9F57-0-0] [lt=10] [dc=0] post trans msg error(tmp_ret=-4653, partition_id=[{tid:1101710651083295, partition_id:6, part_cnt:0},{tid:1101710651083295, partition_id:7, part_cnt:0},***,] msg_union.data_.trx_msg_base={tenant_id:1002, trans_id:{hash:18120109983234875456, inc:25809288, addr:"11.xxx.xx.124:40000", t:1662528031779949}, msg_type:260, trans_time:1662628031780238, sender:{tid:1101710651082976, partition_id:0, part_cnt:0}, receiver:{tid:1101710651083295, partition_id:9, part_cnt:0}, trans_param:[access_mode=1, type=3, isolation=1, magic=17361641481138401520, autocommit=0, consistency_type=0(CURRENT_READ), read_snapshot_type=1(STATEMENT_SNAPSHOT), cluster_version=12885033730, is_inner_trans=0], sender_addr:"11.xxx.xx.124:40000", timestamp:1662529622455257})同时,在 observer 日志中可以看到 500 租户出现了请求积压
req_queue:total_size >0。[2022-09-07 13:47:05.699875] INFO [SERVER.OMT] ob_multi_tenant.cpp:819 [23311][0][Y0-0000000000000000-0-0] [lt=17] [dc=0] dump tenant info(tenant={id:1002, compat_mode:0, unit_min_cpu:"8.000000000000000000e+00", unit_max_cpu:"1.200000000000000000e+01", slice:"0.000000000000000000e+00", slice_remain:"0.000000000000000000e+00", token_cnt:42, sug_token_cnt:42, ass_token_cnt:42, lq_tokens:4, used_lq_tokens:0, stopped:false, idle_us:4395011, recv_hp_rpc_cnt:935154, recv_np_rpc_cnt:10925, recv_lp_rpc_cnt:0, recv_mysql_ps_close_cnt:0, recv_mysql_cnt:7780, recv_task_cnt:219, recv_large_req_cnt:1911, tt_large_quries:45177, pop_normal_cnt:71139024, actives:42, workers:42, nesting workers:7, lq waiting workers:0, req_queue:total_size=15264 queue[0]=15262 queue[1]=0 queue[2]=0 queue[3]=0 queue[4]=2 queue[5]=0 , large queued:0, reserve queued:0, multi_level_queue:total_size=0 queue[0]=0 queue[1]=0 queue[2]=0 queue[3]=0 queue[4]=0 queue[5]=0 queue[6]=0 queue[7]=0 , recv_level_rpc_cnt:cnt[0]=0 cnt[1]=0 cnt[2]=1 cnt[3]=0 cnt[4]=0 cnt[5]=390 cnt[6]=0 cnt[7]=0 , group_map:null, rpc_stat_info: pcode=0x750:cnt=204851 pcode=0x701:cnt=3894 pcode=0x521:cnt=3498 pcode=0x51f:cnt=316})根据日志信息可以知道,当前事务有大量的参与者。查看对应的 SQL 语句,发现对分区表的更新没有带分区键,从而导致所有的分区均参与到分布式事务中。该分区表按月分区,共有 300 个分区。
在事务状态表中查看相关事务的统计,可以看到很多事物的参与者有 300 个左右。
obclient> select count(*) ,trans_id from oceanbase.__all_virtual_trans_stat where partitionlike '%xxxx%' part_trans_action > 2 group by trans_id;
问题原因
业务表分区较多,UPDATE 语句没有指定分区键,从而产生了有较多参与者的分布式事务。而业务的并发又比较高,导致系统内存在大量的分布式事务参与者,而每一个参与者均需要同协调者进行交互,导致网络流量大增,RPC 进程繁忙,clog 同步请求堆积,事务提交缓慢。
解决方案
为问题表添加全局索引,使 UPDATE 语句通过全局索引来更新单个分区的记录,避免所有分区成为事务参与者。
控制分区的数量,删除提前创建的空分区。