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

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. 附录

  • obdiag 官方文档: OceanBase分布式数据库-海量数据 笔笔算数
  • obdiag github地址: GitHub - oceanbase/oceanbase-diagnostic-tool: OceanBase Diagnostic Tool is designed to help OceanBase users quickly gather necessary information and analyze the cause of the problem.
第一篇如何修炼成“神医”——《OceanBase诊断系列》之一
第二篇走进SQL审计视图——《OceanBase诊断系列》之二
第三篇一键操作敏捷诊断工具obdiag收集诊断信息实践——《OceanBase诊断系列》之三
第四篇一键操作敏捷诊断工具obdiag分析OB集群日志设计与实践——《OceanBase诊断系列》之四
第五篇专为OceanBase打造的巡检工具已推出!给OceanBase进行一次体检吧——《OceanBase诊断系列》之五
第六篇obdiag帮你读懂全链路诊断日志——《OceanBase诊断系列》之六
第七篇如何排查合并问题——《OceanBase诊断系列》之七
第八篇一文教你轻松掌握锁冲突问题的排查方法——《OceanBase诊断系列》之八

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/448546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Anaconda 的一些配置

Anaconda 安装及修改环境默认位置 https://blog.csdn.net/qq_54562136/article/details/128932352 最重要的一步&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;改文件夹权限 Anaconda创建、激活、退出、删除虚拟环境 修改pip install 默认安装路径

【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)

文章目录 题目思路解法 题目 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个中间…

数学与简单dp

1205. 买不到的数目 - AcWing题库 import java.util.*;public class Main{public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int m sc.nextInt();System.out.print((n - 1) * (m - 1) - 1);} } 1211. 蚂蚁感冒 - AcWing题库…

告别“死记硬背”,坐席助手让客服新手秒变大咖

在客服行业&#xff0c;新手客服人员常常面临着两大难题&#xff1a;一是需要死记硬背大量的标准答案&#xff0c;二是培训时间长&#xff0c;上岗速度慢。然而&#xff0c;随着科技的发展&#xff0c;这些问题正逐渐得到。今天&#xff0c;我们要为大家介绍一款革命性的客服工…

【考研数学】张宇《1000题》做不下来怎么办?

张宇1000题其实非常考察基础知识&#xff0c;如果你基础没有打好就直接开始刷的话会发现挺难刷下来的 1000题还是更适合在强化阶段来刷&#xff0c;刷早了把心态刷崩掉也没什么用... 基础不好或者0基础的还是建议从简单的1800开始刷起来 同时也要非常注意刷题方法&#xff0…

二叉树——501.二叉搜索树中的众数、 236. 二叉树的最近公共祖先

二叉搜索树中的众数 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c;可以按 任意顺序 返回。 假定 BST …

网络、网络协议模型、UDP编程——计算机网络——day01

今天来到了网络编程&#xff0c;主要讲了网络、网络协议模型以及UDP编程 网络 网络主要是进行&#xff1a;数据传输和数据共享 网络协议模型 OSI协议模型应用层 实际发送的数据表示层 发送的数据是否加密会话层 是否建立会话连接传…

2024暑期实习八股笔记

文章目录 自我介绍MySQL索引索引种类、B树聚簇索引、非聚簇索引联合索引、最左前缀匹配原则索引下推索引失效索引优化 日志、缓冲池redo log&#xff08;重做日志&#xff09;刷盘时机日志文件组 bin log&#xff08;归档日志&#xff09;记录格式写入机制 两阶段提交undo log&…

洛谷 素数环 Prime Ring Problem

题目描述 PDF 输入格式 输出格式 题意翻译 输入正整数 nn&#xff0c;把整数 1,2,\dots ,n1,2,…,n 组成一个环&#xff0c;使得相邻两个整数之和均为素数。输出时&#xff0c;从整数 11 开始逆时针排列。同一个环恰好输出一次。n\leq 16n≤16&#xff0c;保证一定有解。 多…

某宝某猫商品详情页面数据逆向

​​​​​逆向网址 aHR0cHM6Ly93d3cudGFvYmFvLmNvbS8 aHR0cHM6Ly93d3cudG1hbGwuY29tLw 逆向链接 aHR0cHM6Ly9kZXRhaWwudG1hbGwuY29tL2l0ZW0uaHRtP2lkPTc0NDk3NDQ4NTI3NSZwdmlkPTFiMzdmNjUyLTRjNDYtNGM2Ni04MDg4LWRhYmJiZDJhMzJhNSZzY209MTAwNy40MDk4Ni4yNzY3NTAuMCZzcG09YTIxY…

12、MongoDB -- 通过 SpringBoot 整合 Spring Data MongoDB 操作 MongoDB 数据库(传统的同步API编程)

目录 通过 SpringBoot 整合 Spring Data MongoDB 操作 MongoDB 数据库&#xff08;传统的同步API编程&#xff09;演示前提&#xff1a;登录单机模式的 mongodb 服务器命令登录【test】数据库的 mongodb 客户端命令登录【admin】数据库的 mongodb 客户端命令 代码演示同步API编…

基于SpringBoot和PotsGIS的各省地震震发可视化分析

目录 前言 一、后台接口研发 1、控制层实现 2、Mapper访问层 3、空间查询分析 二、前端可视化展示 1、主体地图定义 2、行政区划列表定义 3、行政区划定位 三、数据分析 1、北京市 2、广东省 3、青海省 4、湖南省 总结 前言 在之前的博文中&#xff0c;我们…

【Python】一文详细介绍 plt.rcParamsDefault 在 Matplotlib 中的原理、作用、注意事项

【Python】一文详细介绍 plt.rcParamsDefault 在 Matplotlib 中的原理、作用、注意事项 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程…

每日OJ题_牛客OR57 手套

目录 牛客OR57 手套 解析代码 牛客OR57 手套 手套_牛客题霸_牛客网 class Gloves { public:int findMinimum(int n, vector<int> left, vector<int> right) {} }; 解析代码 class Gloves { public:int findMinimum(int n, vector<int> left, vector<i…

机器学习——Q-Learning

Outline Critic 从头往后&#xff0c;逐渐累积 新时刻跟前一时刻有关 不同的方法得到不同的假设&#xff0c;得到不同的结果 Q-function 在状态s下强制执行a得到对应的奖励 目标网络 targe一直在变 将其中的一个Q进行固定 sample a batch udpdate Q-function …

2023年中国高校大数据挑战赛D题参考论文发布(全网首发)

腾讯文档】2023年大数据挑战赛资料说明 https://docs.qq.com/doc/DSEpWUVFySm1ObFB0 基于数据分析的行业职业技术培训能力评价 摘要 中国是制造业大国&#xff0c;产业门类齐全&#xff0c;每年需要培养大量的技能娴熟的技术工人进入工厂。本文将基于题目给出的数据&#x…

输出int型最大值、最小值的小妙招

如果在算法竞赛中要求输入数据是一个范围很大的数&#xff0c;而你又忘了int型的数据范围&#xff0c;这时该怎么办呢&#xff1f; 比如洛谷P1001号题目&#xff1a; 【题目描述】 输入两个整数a,b&#xff0c;输出它们的和&#xff08;∣a∣,∣b∣≤&#xff09;。 【输入…

微信小程序开发系列(二十)·wxml语法·setData()修改对象类型数据、ES6 提供的展开运算符、delete和rest的用法

目录 1. 新增单个、多个属性 1.1 新增单个属性 1.2 新增多个属性 2. 修改单个、多个属性 2.1 修改单个属性 2.2 修改多个属性 3. 优化 3.1 ES6 提供的展开运算符 3.2 Object.assign()将多个对象合并为一个对象 4. 删除单个、多个属性 4.1 删除单个属性 …

leetcode 热题 100_旋转图像

题解一&#xff1a; 翻转数组&#xff1a;先将数组沿右上-左下对角线翻转&#xff0c;再将数组上下翻转。 class Solution {public void rotate(int[][] matrix) {int n matrix.length;for (int i 0; i < n; i) {//沿右上-左下对角线翻转for (int j 0; j < n - i - 1…

Corel会声会影视频编辑软件英文名是Corel VideoStudio2023

Corel会声会影视频编辑软件英文名是Corel VideoStudio2023&#xff0c;可以抓取、编制和导出多种常见的视频格式。介绍整理从早期的会声会影9、会声会影10后到会声会影X系列版本包括X2、X3、X4、X5、X6、X7、X8、X9、X10&#xff0c;2018&#xff0c;2019&#xff0c;2020&…