首页 > 其他分享 >轻松掌握锁冲突问题的排查方法——《OceanBase诊断系列》之八

轻松掌握锁冲突问题的排查方法——《OceanBase诊断系列》之八

时间:2024-03-12 19:59:18浏览次数:29  
标签:事务 20 NO OceanBase 之八 排查 bigint NULL id

1. 前言

OceanBase数据库通过两阶段封锁机制确保读写事务并发控制的正确性。在高冲突场景下,事务处理中经常会遇到行锁冲突的问题。然而,许多OceanBase用户对于何时发生锁冲突,锁冲突的表现如何,以及如何排查锁冲突的原因,甚至于定位具体的行与锁冲突的会话。本文为读者提供一个系统的方法,帮助大家有效排查和解决锁冲突问题。

2. OceanBase 3.x & 4.1 锁冲突问题排查指北

以行锁为单位,可以抽象出与行锁有密切关系的两个对象:行锁的持有者,行锁的等待者。如果能够将这两个信息进行监控,那么对排查行锁的相关问题,将带来很大的帮助。本质来讲,行锁冲突都是由事务引起的。上述两个对象,都是隶属于事务,因此对活跃事务的监控也是必不可少的。基于以上分析,我们对不同的角色,分别实现了不同的虚拟表,用于展示上述信息,具体为:行锁持有者(__all_virtual_trans_lock_stat),行锁等待者(__all_virtual_lock_wait_stat),活跃事务(__all_virtual_trans_stat

2.1 活跃事务(__all_virtual_trans_stat)

OceanBase (root@oceanbase)> desc __all_virtual_trans_stat;
+---------------------------+---------------+------+-----+---------+-------+
| Field                     | Type          | Null | Key | Default | Extra |
+---------------------------+---------------+------+-----+---------+-------+
| tenant_id                 | bigint(20)    | NO   | PRI | NULL    |       |
| svr_ip                    | varchar(32)   | NO   | PRI | NULL    |       |
| svr_port                  | bigint(20)    | NO   | PRI | NULL    |       |
| inc_num                   | bigint(20)    | NO   | PRI | NULL    |       |
| session_id                | bigint(20)    | NO   |     | NULL    |       |
| proxy_id                  | varchar(512)  | NO   |     | NULL    |       |
| trans_type                | bigint(20)    | NO   |     | NULL    |       |
| trans_id                  | varchar(512)  | NO   |     | NULL    |       |
| is_exiting                | bigint(20)    | NO   |     | NULL    |       |
| is_readonly               | bigint(20)    | NO   |     | NULL    |       |
| is_decided                | bigint(20)    | NO   |     | NULL    |       |
| active_memstore_version   | varchar(64)   | NO   |     | NULL    |       |
| partition                 | varchar(64)   | NO   |     | NULL    |       |
| participants              | varchar(1024) | NO   |     | NULL    |       |
| autocommit                | bigint(20)    | NO   |     | NULL    |       |
| trans_consistency         | bigint(20)    | NO   |     | NULL    |       |
| ctx_create_time           | timestamp(6)  | YES  |     | NULL    |       |
| expired_time              | timestamp(6)  | YES  |     | NULL    |       |
| refer                     | bigint(20)    | NO   |     | NULL    |       |
| sql_no                    | bigint(20)    | NO   |     | NULL    |       |
| state                     | bigint(20)    | NO   |     | NULL    |       |
| part_trans_action         | bigint(20)    | NO   |     | NULL    |       |
| lock_for_read_retry_count | bigint(20)    | NO   |     | NULL    |       |
+---------------------------+---------------+------+-----+---------+-------+
23 rows in set (0.01 sec)

该表中展示了该集群中所有参与者上下文的当前状态,关键参数说明如下:
svr_ip           		   表示该上下文创建的server地址;
session_id				   表示该事务所对应session的唯一标识;
proxy_id,		   	       表示客户端(proxy/java client)所对应的”ip:port“
trans_id,		   	       表示事务的唯一标识
is_exiting,		   	   当前的事务上下文是否正在退出
partition,		           当前的事务上下文在哪个分区上创建
participants,	           当前事务的参与者列表
ctx_create_time,          事务上下文创建的时间;
ref,			           表示context当前的引用计数
sql_no,			       表示当前context上最后一次执行sql的sql_no
state,			           表示context当前的状态:INIT/PREPARE/COMMIT/ABORT/CLEAR,值域为0/1/2/3/4
part_trans_action, 	   表示当前context最后一次操作的动作:START_TASK/END_TASK/COMMIT
lock_for_read_retry_count  表示当前context在table scan过程中,是否遇到过锁冲突重试,值越大,表示冲突越严重。

2.2 行锁持有者(__all_virtual_trans_lock_stat)

OceanBase (root@oceanbase)> desc __all_virtual_trans_lock_stat;
+-----------------+--------------+------+-----+---------+-------+
| Field           | Type         | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| tenant_id       | bigint(20)   | NO   | PRI | NULL    |       |
| trans_id        | varchar(512) | NO   | PRI | NULL    |       |
| svr_ip          | varchar(32)  | NO   | PRI | NULL    |       |
| svr_port        | bigint(20)   | NO   | PRI | NULL    |       |
| partition       | varchar(64)  | NO   | PRI | NULL    |       |
| rowkey    | varchar(512) | NO   | PRI | NULL    |       |
| session_id      | bigint(20)   | NO   |     | NULL    |       |
| proxy_id        | varchar(512) | NO   |     | NULL    |       |
| ctx_create_time | timestamp(6) | YES  |     | NULL    |       |
| expired_time    | timestamp(6) | YES  |     | NULL    |       |
+-----------------+--------------+------+-----+---------+-------+
10 rows in set (0.00 sec)

该表记录以行为单位,记录了当前集群所有活跃事务持有行的相关信息;关键参数说明如下:

rowkey,表示内部表示的行消息
session_id,proxy_id,trans_id等其他参数都是为了跟活跃事务对应起来。

2.3 行锁等待者(写锁)__all_virtual_lock_wait_stat

OceanBase (root@oceanbase)> desc __all_virtual_lock_wait_stat;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| svr_ip          | varchar(32)         | NO   | PRI | NULL    |       |
| svr_port        | bigint(20)          | NO   | PRI | NULL    |       |
| table_id        | bigint(20)          | NO   | PRI | NULL    |       |
| rowkey          | varchar(512)        | NO   | PRI | NULL    |       |
| addr            | bigint(20) unsigned | NO   | PRI | NULL    |       |
| need_wait       | tinyint(4)          | NO   |     | NULL    |       |
| recv_ts         | bigint(20)          | NO   |     | NULL    |       |
| lock_ts         | bigint(20)          | NO   |     | NULL    |       |
| abs_timeout     | bigint(20)          | NO   |     | NULL    |       |
| try_lock_times  | bigint(20)          | NO   |     | NULL    |       |
| time_after_recv | bigint(20)          | NO   |     | NULL    |       |
| session_id      | bigint(20)          | NO   |     | NULL    |       |
| block_session_id | bigint(20)          | NO   |     | NULL    |       |
| type             | bigint(20)          | NO   |     | NULL    |       |
| lock_mode        | bigint(20)          | NO   |     | NULL    |       |
+-----------------+---------------------+------+-----+---------+-------+
12 rows in set (0.00 sec)

该表统计了当前集群中,所有正在等待行锁的请求/语句的相关信息,关键参数说明如下:
session_id,proxy_id,trans_id等其他参数都是为了跟活跃事务对应起来,不再一一赘述。
lock_ts,表示该请求开始等锁的时间点;(us)
abs_timeout,该语句的绝对超时时间(us)
try_lock_times,表示该语句曾经尝试过加锁的次数,值越大,表示锁冲突越严重
block_session_id, 表示第一个等在这个行上的事务的session

3. OB >= 4.2 锁冲突问题排查指北

随着 4.2 版本(G)V$OB_LOCKS视图的引入,锁冲突问题排查有了更加简单、直接的方法,我们基本实现了在一张视图内排查锁冲突问题。

3.1 (G)V$OB_LOCKS 介绍

字段类型是否为 NULL描述
SVR_IPVARCHAR2(46)NO持锁或请求锁的 OBServer 节点的 IP 地址
SVR_PORTNUMBER(38)NO持锁或请求锁的 OBServer 节点的端口号
TENANT_IDNUMBER(38)NO持锁或请求锁的租户的 ID
TRANS_IDNUMBER(38)NO持锁或请求锁的事务 ID
TYPEVARCHAR2(9)NO锁类型:TM:表锁TX:事务锁TR:行锁
ID1NUMBERNO锁标识符 1:表锁:可能是 TABLE_ID,也可能是 TABLET_ID事务锁:TX_ID行锁:TABLET_ID
ID2VARCHAR2(553)NO锁标识符 2:表锁:NULL事务锁:NULL行锁:TX_ID + 行 rowkey
LMODEVARCHAR2(4)NO当前持有锁的模式:NONE:表示未持有任何锁SS:ROW SHARESX:ROW EXCLUSIVES:SHARESSX:SHARE ROW EXCLUSIVEX:EXCLUSIVE
REQUESTVARCHAR2(8)NO当前请求锁的模式:NONE:表示未请求任何锁SS:ROW SHARESX:ROW EXCLUSIVES:SHARESSX:SHARE ROW EXCLUSIVEX:EXCLUSIVE
CTIMENUMBER(38)NO持有或等待锁的时间,单位为秒
BLOCKNUMBERNO表示当前事务请求的锁是否被其他事务持有:0:表示请求的锁未被其他事务持有,即该事务持有锁1:表示请求的锁被其他事务持有,即该事务被阻塞

锁视图中TYPE列表示了锁的类型,目前 Oceanbase 主要展示以下 3 种类型的锁:

  • 表锁(TM):即表 / 分区(tablet)上的锁。通常 insert / update / delete 等 dml 操作会产生分区级表锁锁,而 ddl 操作会产生表级表锁,这是由表锁的设计决定的。
  • 行锁(TR):即写行时上的锁。在 Oceanbase 的实现中,并不存在通常意义上理解的狭义行锁(即支持读 / 写等多种模式的实际存在的锁结构),而是通过行上是否有活跃事务来表现。因此,行锁可以理解为事务锁的一种特例。
  • 事务锁(TX):最常见的锁,通常可以理解为在事务内做过写操作即会产生事务锁。事务锁可以理解为行锁的退化形式,当无法维护事务到行的映射关系时,行锁即会转换成事务锁。

行锁和事务锁有着密切的关联,为了避免歧义和混乱,在(G)V$OB_LOCKS的实际实现中,我们不区分行锁和事务锁的退化 / 特例关系,而是采用了全量维护的方式。这意味着,如果一个事务持有行锁,那么其一定也持有自己的事务锁。

3.2 锁冲突排查流程

由于(G)V$OB_LOCKS目前不展示实际持锁的 session_id,因此以下的排查手段都只获取持锁的 trans_id。

  • 应急场景

在获取到持锁的 trans_id 后,通过(G)V$OB_TRANSACTION_PARTICIPANTS关联 trans_id 对应的 session_id,并通过kill session_id回滚对应事务。

  • 非应急场景

在获取到持锁的 trans_id 后,确认该事务为什么一直不解锁。不解锁的原因非常多样,可以通过 trans_id 在 observer.log 中过滤相关日志。常见的不解锁原因有以下几个:

  1. 长事务,即持锁事务本身很复杂,导致其长时间执行不结束。可通过持锁事务的 trans_id 过滤__all_virtual_processlist表,观察事务是否悬挂在某条 sql 请求上;或通过日志观察事务的对应 trace 中 slow query 相关的日志,定位哪条 sql 执行慢;
  2. 锁冲突,即该事务也在等其他事务的锁。对于该问题可先通过(G)V$OB_LOCKS过滤该 trans_id,检查是否有BLOCK=1的行,若有则进一步确认该持锁事务的不解锁原因,若无则通过 trans_id 过滤 observer.log 日志,确认悬挂过程中是否有其请求锁时报 -6005 报错(需要确认非该 trans_id 持锁报 -6005,例如该 trans_id 为 conflict_tx_id)。

说明:日志中-6x的错误码是事务相关的,其-6003/-6004/-6005和锁相关。

-6001:ERROR 6001 (25000): OB-6001:Transaction set changed during the execution:事务在执行过程中SET改变。事务回滚。
-6002: ERROR 6002 (40000): OB-6002:transaction is rolled back:事务被回滚。
-6003:ERROR 1205 (HY000): OB-1205:Lock wait timeout exceeded; try restarting transaction:锁等待时间已经超过超时时间,尝试重新启动事务。当前SQL失败,不改变事务状态,需要应用重试或做其他处理。 
-6004: ERROR 6004 (HY000): OB-6004:Shared lock conflict:执行INSERT/UPDATE/DELETE时,行锁冲突。
-6005:ERROR 6005 (HY000): OB-6005: Trylock row conflict:获取行锁冲突。
-6210:ERROR (25000): OB-4012:Transaction is timeout:事务超时。需要明确发起回滚才可以继续复用当前连接。
-6211:ERROR 6211 (25000): OB-6002:Transaction is killed:事务被杀。数据库端事务会回滚。
-6213:ERROR 6002 (HY000): OB-6002:Transaction context does not exist:事务内容不存在。数据库端事务会回滚。
-6224: ERROR 6002 (25000): OB-6002:transaction need rollback:事务需要回滚。不需要客户端发起回滚,数据库端事务会回滚。
-6225:ERROR 4012 (25000): OB-4012:Transaction result is unknown:事务结果未知。数据库端事务可能已提交或者回滚。需要业务重试。
-6226: ERROR 1792 (25006): OB-1792:Cannot execute statement in a READ ONLY transaction:不能在只读事务中执行语句。

同时如果你的环境是通过ocp部署的,还可以通过里面的SQL诊断的TOP SQL页面过滤重试次数大于0的SQL,也可以初步筛查可能的SQL.

1709171343

如果不是通过ocp部署的集群,也可以通过查询gv$sql_audit(4.x版本以后是gv$ob_sql_audit) 其中的retry_cnt字段数值大于0,是有可能发生了锁冲突的。是否真的发生了锁冲突,需要进一步通过日志来确认。在日志中出现-6003/-6004-6005的错误码则发生了锁冲突。日志分析推荐一个非常轻量的黑屏小工具obdiag。链接: OceanBase分布式数据库-海量数据 笔笔算数  , 安装配置好后可执行obdiag analyze log分析observer的日志,看是否有-6003/-6004-6005的错误日志。

4. 锁冲突排查思维导图

1709137633

5. 王炸:obdiag 一键诊断锁冲突

obdiag官网文档参见: OceanBase分布式数据库-海量数据 笔笔算数

使用 obdiag rca 命令可帮助 OceanBase 数据库相关的诊断信息分析,目前支持对 OceanBase 的异常场景进行分析,找出可能导致问题的原因。

obdiag rca list # 列出所有的根因分析场景
obdiag rca run --scene=<scene_name> #执行具体场景的根因分析

scene_name 包含如下:

  • disconnection:一键断连诊断,基于obproxy的诊断日志。
  • major_hold: 一键卡合并诊断。
  • lock_conflict: 一键锁冲突诊断。

示例:分析卡合并场景

obdiag rca run --scene=lock_conflict

6. 附录

第一篇如何修炼成“神医”——《OceanBase诊断系列》之一
第二篇走进SQL审计视图——《OceanBase诊断系列》之二
第三篇一键操作敏捷诊断工具obdiag收集诊断信息实践——《OceanBase诊断系列》之三
第四篇一键操作敏捷诊断工具obdiag分析OB集群日志设计与实践——《OceanBase诊断系列》之四
第五篇专为OceanBase打造的巡检工具已推出!给OceanBase进行一次体检吧——《OceanBase诊断系列》之五
第六篇obdiag帮你读懂全链路诊断日志——《OceanBase诊断系列》之六
第七篇如何排查合并问题——《OceanBase诊断系列》之七
第八篇一文教你轻松掌握锁冲突问题的排查方法——《OceanBase诊断系列》之八

标签:事务,20,NO,OceanBase,之八,排查,bigint,NULL,id
From: https://blog.csdn.net/OceanBaseGFBK/article/details/136478671

相关文章

  • Smb3.0多通道技术及故障排查
    Smb3.0多通道技术有RSS和RDMA网卡或两种网卡叠加实现微软是建议网卡带有RSS和RDMA,因为RDMA网卡很贵我没有条件测试。以下针对RSS-SMBRSS(receivesidescaling)功能中文名叫“接收端调整”,CPU多核心时,每核心(非超线程)可用一个线程发起一个通道。SMB多通道的要求由于默认情......
  • k8s生产中遇到什么特别映像深刻的问题吗,问题排查解决思路是怎么样的?
    答:前端的lb负载均衡服务器上的keepalived出现过脑裂现象。1、当时问题现象是这样的,vip同时出现在主服务器和备服务器上,但业务上又没受到影响;2、这时首先去查看备服务器上的keepalived日志,发现有日志信息显示凌晨的时候备服务器出现了vrrp协议超时,所以才导致了备服务器接管了vip;查......
  • 查看 OceanBase 执行计划
    使用benchmarksql压测数据库,产生高消耗的sql并测试数据库性能压测环境部署benchmarksql下载gitclonehttps://github.com/meiq4096/benchmarksql-5.0.git修改配置文件vi./run/props.obdb=oracledriver=com.alipay.oceanbase.obproxy.mysql.jdbc.Driverconn=jdbc:ocean......
  • datax从mysql迁移数据到OceanBase
    datax部署下载dataxdatax下载地址安装dataxtar-zxvfdatax.tar.gz使用datax使用配置文件{"job":{"setting":{"speed":{"channel":4},"errorLimit":{......
  • mysqldump从mysql迁移数据到OceanBase
    使用mysqldump导出数据/usr/bin/mysqldump--single-transaction-Bemployees-S/data/mysql/mysql.sock-uroot-p>dump.sqlob使用source加载obclient-P2883-h192.168.56.20-uroot@mq_t1-A校验数据使用统计信息两个数据库收集统计信息的命令相同收集统计信息an......
  • 多节点oceanbase 集群部署
    安装前准备硬件要求CPU最少2核磁盘最少19G文件系统EXT4戓XFS关闭透明大页echonever>/sys/kernel/mm/redhat_transparent_hugepage/enabled确认操作系统版本是否支持[root@innodb-cluster01~]#cat/etc/redhat-releaseRedHatEnterpriseLinuxServerrelease7.9......
  • 排查 dotNET Core 程序内存暴涨的问题
    0.问题新版本上线之后,发现内存猛涨,入站流量猛增,不清楚具体原因,部分接口提示OOM异常,随后Pod直接崩溃无限重启。1.准备Pod已经接入了NewRelic和Graylog,但是仍然没有办法找到真正的罪魁祸手,此时只能进入Pod容器当中抓取内存Dump信息。我们容器的基础镜像是基于Apli......
  • 排查 dotNET Core 程序内存暴涨的问题
    0.问题新版本上线之后,发现内存猛涨,入站流量猛增,不清楚具体原因,部分接口提示OOM异常,随后Pod直接崩溃无限重启。1.准备Pod已经接入了NewRelic和Graylog,但是仍然没有办法找到真正的罪魁祸手,此时只能进入Pod容器当中抓取内存Dump信息。我们容器的基础镜像是基于Apli......
  • 网站服务器问题排查常用命令
       访问最频繁的url awk'{print$7}'/www/wwwlogs/pap.log|sort|uniq-c|sort-rn|head-n20 指定时间段访问最频繁的ipawk'{print$7}'/www/wwwlogs/p.log|sort|uniq-c|sort-rn|head-n20cat/www/wwwlogs/p.cn.log |awk'$4>......
  • mysql cpu 1300% 耗尽服务器cpu资源 系统变慢问题排查解决
    每到下午用户使用高峰期发现16核的服务器mysql的cpu经常占用超过1300% 总cpu占用95%以上,以前0.1秒的查询居然要查询10几秒用showprocesslist  命令查看mysql发现很多 select*frome_task_assignment_odmwheretask_code='xxx'看了下这个表有400多万数据,task_code没......