[kingbase锁等待问题分析]

参考文章:https://www.modb.pro/db/70021

概述

为了确保复杂的事务可以安全地同时运行,kingbase(PostgreSQL)提供了各种级别的锁来控制对各种数据对象的并发访问,使得对数据库关键部分的更改序列化。事务并发运行,直到它们尝试获取互相冲突的锁为止(比如两个事务更新同一行时)。当多个事务同时在数据库中运行时,并发控制是一种用于维持一致性和隔离性的技术,在kingbase(PostgreSQL)中,使用快照隔离Sanpshot Isolation (简称SI) 来实现多版本并发控制,同时以两阶段锁定 (2PL) 机制为辅。在执行DDL时使用2PL,在执行DML时使用SI。
在数据库中,同样也存在着各式各样的锁,表级锁、行级锁、页锁等等,数据库的并发能力除了和它的并发控制机制有关, 还和数据库的锁粒度控制息息相关,粒度越细冲突范围就越小,并发能力就越强。锁的最终目的无外乎是为了保证数据的一致性和完整性

kingbase锁矩阵

锁矩阵

场景

Z银行客户A系统 性能压测,压测时监控数据库服务器,发现数据库存在长连接情况,对长链接的会话进行锁分析。
经典获取锁信息的SQL:

SELECT blocked_locks.pid  AS blocked_pid,
       blocked_activity.usename  AS blocked_user,
       blocked_activity.client_addr as blocked_client_addr,
       blocked_activity.client_hostname as blocked_client_hostname,
       blocked_activity.application_name as blocked_application_name,
       blocked_activity.wait_event_type as blocked_wait_event_type,
       blocked_activity.wait_event as blocked_wait_event,
       blocked_activity.query   AS blocked_statement,
       blocked_activity.xact_start AS blocked_xact_start,
       blocking_locks.pid  AS blocking_pid,
       blocking_activity.usename AS blocking_user,
       blocking_activity.client_addr as blocking_client_addr,
       blocking_activity.client_hostname as blocking_client_hostname,
       blocking_activity.application_name as blocking_application_name,
       blocking_activity.wait_event_type as blocking_wait_event_type,
       blocking_activity.wait_event as blocking_wait_event,
       blocking_activity.query AS current_statement_in_blocking_process,
       blocking_activity.xact_start AS blocking_xact_start
FROM  pg_catalog.pg_locks   blocked_locks
   JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
   JOIN pg_catalog.pg_locks  blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
   JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted ORDER BY blocked_activity.pid ;

查询结果:
查询结果1
通过上述的SQL查询找到了相互阻塞的SQL,分析等待事件,pid 4183128 在等待一个事务提交,而pid 4183129 是在等客户端完成操作。
两个事务操作的不是同一张表,不应该相互阻塞才对,再次确认一下各自的阻塞pid。
查询阻塞pid SQL:

SELECT pid,pg_blocking_pid(pid),wait_event_type,wait_event,query from pg_stat_activity where pid =xxxxx;

查询结果2
这里说明一下,pid改变,是使用两次压测的查询结果。
查询结果分析:
通过系统函数pg_blocking_pid可以看到阻塞事务pid和等锁类型,分析阻塞update操作的确实是select操作的事务,锁类型是lock,锁事件是等待事务提交,而select操作的锁类型是客户端操作,等待事件是等待客户端操作提交。
考虑到两个SQL并不是操作的一个表,且select操作不应该阻塞DML操作,因此继续使用第二个经典的SQL来查询一下。
经典SQL2:

with      
t_wait as      
(      
  select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,     
  a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,      
  b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name     
    from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted     
),     
t_run as     
(     
  select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,     
  a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,     
  b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name     
    from pg_locks a,pg_stat_activity b where a.pid=b.pid and a.granted     
),     
t_overlap as     
(     
  select r.* from t_wait w join t_run r on     
  (     
    r.locktype is not distinct from w.locktype and     
    r.database is not distinct from w.database and     
    r.relation is not distinct from w.relation and     
    r.page is not distinct from w.page and     
    r.tuple is not distinct from w.tuple and     
    r.virtualxid is not distinct from w.virtualxid and     
    r.transactionid is not distinct from w.transactionid and     
    r.classid is not distinct from w.classid and     
    r.objid is not distinct from w.objid and     
    r.objsubid is not distinct from w.objsubid and     
    r.pid <> w.pid     
  )      
),      
t_unionall as      
(      
  select r.* from t_overlap r      
  union all      
  select w.* from t_wait w      
)      
select locktype,datname,relation::regclass,page,tuple,virtualxid,transactionid::text,classid::regclass,objid,objsubid,     
string_agg(     
'Pid: '||case when pid is null then 'NULL' else pid::text end||chr(10)||     
'Lock_Granted: '||case when granted is null then 'NULL' else granted::text end||' , Mode: '||case when mode is null then 'NULL' else mode::text end||' , FastPath: '||case when fastpath is null then 'NULL' else fastpath::text end||' , VirtualTransaction: '||case when virtualtransaction is null then 'NULL' else virtualtransaction::text end||' , Session_State: '||case when state is null then 'NULL' else state::text end||chr(10)||     
'Username: '||case when usename is null then 'NULL' else usename::text end||' , Database: '||case when datname is null then 'NULL' else datname::text end||' , Client_Addr: '||case when client_addr is null then 'NULL' else client_addr::text end||' , Client_Port: '||case when client_port is null then 'NULL' else client_port::text end||' , Application_Name: '||case when application_name is null then 'NULL' else application_name::text end||chr(10)||      
'Xact_Start: '||case when xact_start is null then 'NULL' else xact_start::text end||' , Query_Start: '||case when query_start is null then 'NULL' else query_start::text end||' , Xact_Elapse: '||case when (now()-xact_start) is null then 'NULL' else (now()-xact_start)::text end||' , Query_Elapse: '||case when (now()-query_start) is null then 'NULL' else (now()-query_start)::text end||chr(10)||      
'SQL (Current SQL in Transaction): '||chr(10)||    
case when query is null then 'NULL' else query::text end,      
chr(10)||'--------'||chr(10)      
order by      
  (  case mode      
    when 'INVALID' then 0     
    when 'AccessShareLock' then 1     
    when 'RowShareLock' then 2     
    when 'RowExclusiveLock' then 3     
    when 'ShareUpdateExclusiveLock' then 4     
    when 'ShareLock' then 5     
    when 'ShareRowExclusiveLock' then 6     
    when 'ExclusiveLock' then 7     
    when 'AccessExclusiveLock' then 8     
    else 0     
  end  ) desc,     
  (case when granted then 0 else 1 end)    
) as lock_conflict    
from t_unionall     
group by     
locktype,datname,relation,page,tuple,virtualxid,transactionid::text,classid,objid,objsubid ;    

SQL2查询结果:
查询结果3
查询结果3-2
分析SQL2查询结果,发现update实际被另一个update阻塞。
找到了相互阻塞的事务,现在重点关注的是select操作为什么没有commit,这就需要看一下业务的代码了,先现象和分析结果反馈给了业务侧开发,开发反馈是方法上之前有一个事务的注解,去掉之后select正常提交,未在出现锁等待情况。

问题解决方案:
1 数据库端添加超时参数,idle_in_transaction_session_timeout,单位ms。
2 业务代码侧解决。

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

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

相关文章

Ubuntu服务器/工作站常见故障修复记录

日常写代码写方案文档&#xff0c;偶尔遇上服务器出现问题的时候&#xff0c;也需要充当一把运维工程师&#xff0c;此帖用来记录服务器报错的一些解决方案&#xff0c;仅供参考&#xff01; 文章目录 一、服务器简介二、机箱拆解三、基本操作3.1 F2进入BIOS3.2 F12进入Boot Me…

基于Vue+SpringBoot的个人健康管理系统

项目编号&#xff1a; S 040 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S040&#xff0c;文末获取源码。} 项目编号&#xff1a;S040&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健…

判断序列Series中的值是否都不一样 PandasSeries中的方法:is_unique()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断序列Series中的值是否都不一样 PandasSeries中的方法&#xff1a; is_unique() 选择题 请问下列程序运行的的结果是&#xff1a; import pandas as pd s1 pd.Series([1,2,3]) print("…

Kafka 集群如何实现数据同步

Kafka 介绍 Kafka 是一个高吞吐的分布式消息系统&#xff0c;不但像传统消息队列&#xff08;RaabitMQ、RocketMQ等&#xff09;那样能够【异步处理、流量消峰、服务解耦】 还能够把消息持久化到磁盘上&#xff0c;用于批量消费。除此之外由于 Kafka 被设计成分布式系统&…

机器学习【02】在 Pycharm 里使用 Jupyter Notebook

只有 Pycharm 的 Professional 版才支持 Jupyter Notebook 本教程结束只能在pycharm中使用&#xff0c;下载的库在pycharm选中的虚拟环境中 ssh -L localhost:9999:localhost:8888 usernameip这句话每次都要用 准备 1.服务器安装jupyter sudo snap install jupyter2.在 Jup…

Unity 引擎宣布:自 2024 年起,开发者需支付费用!

Unity引擎宣布的新的收费模式&#xff0c;从2024年1月1日开始&#xff0c;根据游戏的安装量来对开发者进行收费。具体来说&#xff0c;每次游戏被下载时&#xff0c;UnityRuntime也会被安装&#xff0c;因此可能会产生额外的费用。对于开发者来说&#xff0c;需要注意以下几点&…

蓝桥杯第597题 跑步锻炼 C++ 日期模板题(模拟经典)

题目 跑步锻炼https://www.lanqiao.cn/problems/597/learning/?page1&first_category_id1&name%E8%B7%91%E6%AD%A5%E9%94%BB%E7%82%BC 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝每天都锻炼身…

【数据结构 —— 堆的实现(顺序表)】

数据结构 —— 堆的实现&#xff08;顺序表&#xff09; 一.堆1.1堆的定义及结构1.1.1.堆的定义1.1.2.堆的性质1.1.3.堆的结构 二.堆的实现2.1.头文件的实现 —— &#xff08;Heap.h&#xff09;2.2.源文件的实现 —— &#xff08;Heap.c&#xff09;2.2.1.小堆的源文件2.2.2…

Alibaba Cloud Linux 3安装Docker

进行docker安装&#xff08;以社区版为例&#xff09; 添加docker-ce的dnf源 dnf config-manager --add-repohttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo2.安装Alibaba Cloud Linux 3专用的dnf源兼容插件 dnf -y install dnf-plugin-releasever-adap…

Ubuntu中安装搜狗输入法教程(详细图文教程)

习惯了使用搜狗输入法&#xff0c;这里总结了Ubuntu系统下安装搜狗输入法的详细教程&#xff0c;每个步骤都很详细&#xff0c;耐心安装。 搜狗输入法是一款功能强大、使用方便的输入法&#xff0c;能够有效提升用户在Ubuntu系统中的输入体验。 目录 一、下载搜狗安装包1.1 搜…

Python可迭代对象排序:深入排序算法与定制排序

更多Python学习内容&#xff1a;ipengtao.com 排序在计算机科学中是一项基础而关键的操作&#xff0c;而Python提供了强大的排序工具来满足不同场景下的排序需求。本文将深入探讨Python中对可迭代对象进行排序的方法&#xff0c;涵盖基础排序算法、sorted函数的应用、以及定制排…

算法-中等-链表-两数相加

记录一下算法题的学习11 两数相加 题目&#xff1a;给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字…

物流实时数仓:数仓搭建(ODS)

系列文章目录 物流实时数仓&#xff1a;采集通道搭建 物流实时数仓&#xff1a;数仓搭建 文章目录 系列文章目录前言一、IDEA环境准备1.pom.xml2.目录创建 二、代码编写1.log4j.properties2.CreateEnvUtil.java3.KafkaUtil.java4.OdsApp.java 三、代码测试总结 前言 现在我们…

Centos7 离线安装 CDH7.1.7

1. 安装CDH的准备工作&#xff08;所有节点都要执行&#xff09; 1.1 准备环境 角色 IP k8s-master 192.168.181.129 k8s-node1 192.168.181.130 k8s-node2 192.168.181.131 1.2 安装JDK # https://www.oracle.com/java/technologies/downloads/#java11 wget rpm -ivh…

C#,数值计算——插值和外推,Powvargram的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Functor for variogram v(r)ar^b, /// where b is specified, a is fitted from the data. /// </summary> public class Powvargram { private do…

技术分享 | 在 IDE 插件开发中接入 JCEF 框架

项目背景 当前的开发环境存在多种不同语言的 IDE&#xff0c;如 JetBrains 全家桶、Eclipse、Android Studio 和 VS Code 等等。由于每个 IDE 各有其特定的语言和平台要求&#xff0c;因此开发 IDE 插件时&#xff0c;需要投入大量资源才能尽可能覆盖大部分工具。同时&#xf…

【精选】框架初探篇之——MyBatis的CRUD及配置文件

MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…

SOLIDWORKS 2024新功能之CAM篇

SOLIDWORKS 2024 新功能 CAM篇目录概述 • 附加探测周期参数 • 反转切割的固定循环螺纹加工 • 包含装配体的零件的正确进给/速度数据 • Heidenhain 探测类型 • 2.5 轴特征向导中岛屿的终止条件 • 链接轮廓铣削操作的切入引导和切出引导参数 • 螺纹铣削操作的最小孔…

从0开始学习JavaScript--深入了解JavaScript框架

JavaScript框架在现代Web开发中扮演着关键角色&#xff0c;为开发者提供了丰富的工具和抽象层&#xff0c;使得构建复杂的、高性能的Web应用变得更加容易。本文将深入探讨JavaScript框架的核心概念、常见框架的特点以及它们在实际应用中的使用。 JavaScript框架的作用 JavaSc…

NX二次开发UF_CSYS_edit_matrix_of_object 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_edit_matrix_of_object Defined in: uf_csys.h int UF_CSYS_edit_matrix_of_object(tag_t object_id, tag_t matrix_id ) overview 概述 Updates the specified coordinat…
最新文章