[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_locksJOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pidJOIN pg_catalog.pg_locks  blocking_locks ON blocking_locks.locktype = blocked_locks.locktypeAND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASEAND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relationAND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.pageAND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tupleAND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxidAND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionidAND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classidAND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objidAND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubidAND blocking_locks.pid != blocked_locks.pidJOIN 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.mzph.cn/news/166051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关闭EntityFramework日志输出SQL

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; EntityFramework日志输出SQL 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; EntityFramework日志输出SQL&#xff0c;造成发布后&#xff0c;无效日志太多&#xff0c;且容器化部…

Linux安全之AIDE系统入侵检测工具安装和使用

一、AIDE 系统入侵检测工具简介 AIDE&#xff0c;全称为Advanced Intrusion Detection Environment&#xff0c;是一个主要用于检测文件完整性的入侵检测工具。它能够构建一个指定文件的数据库&#xff0c;并使用aide.conf作为其配置文件。AIDE数据库能够保存文件的各种属性&am…

Django(十、中间件)

文章目录 一、中间件的介绍中间件有什么用中间件功能自定义中间中间件的顺序 一、中间件的介绍 中间件顾名思义&#xff0c;是介于request与response处理之间的一道处理过程&#xff0c;相对比较轻量级&#xff0c;并且在全局上改变django的输入与输出。因为改变的是全局&…

U盘启动制作工具Rufus

U盘启动制作工具Rufus 下载U盘启动制作工具Rufus&#xff0c;进入Rufus官网&#xff1a;http://rufus.ie/en/&#xff0c;打开之后往后滑动&#xff0c;找到download即可点击下载。 需要插入U盘 首先需要插入U盘&#xff0c;如果U盘有重要文件一定要备份&#xff0c;然后右键…

mysql安装亲测有效

http://t.csdnimg.cn/UHuy4

Grails 启动

Grails系列 Grails项目启动 文章目录 Grails系列Grails一、项目创建二、可能的问题1.依赖下载2.项目导入到idea失败3.项目导入到idea后运行报错 Grails Grails是一款基于Groovy语言的Web应用程序框架&#xff0c;它使用了许多流行的开源技术&#xff0c;如Spring Framework、…

Go语言初始化已有环境,跟踪已有依赖环境

在Go语言中&#xff0c;go.mod文件是Go模块的管理文件&#xff0c;用于跟踪和管理项目的依赖关系。go.sum 文件是 Go 语言模块的另一个关键文件&#xff0c;它记录了项目依赖的确切版本以及相应的哈希值。如果你得到了一个包含go.mod和go.sum文件的Go代码&#xff0c;&#xff…

内衣洗衣机怎么选?性价比高的小型洗衣机推荐

在机器解放了双手的时代中&#xff0c;洗衣机走进了千家万户&#xff0c;虽然在某种程度上缓解了人们手洗衣服的压力&#xff0c;但还是有不少人选择了人工手洗自己的内衣内裤&#xff0c;甚至连袜子都是手工洗的&#xff0c;这让人很是郁闷&#xff0c;倒不是说洗衣机不方便&a…

SpringBoot整合SpringSecurity+jwt+knife4生成api接口(从零开始简单易懂)

一、准备工作 ①&#xff1a;创建一个新项目 1.事先创建好一些包 ②&#xff1a;引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency>&…

可以远程控制电脑桌面的软件有哪些?

随着电脑办公的普及&#xff0c;人们对于远程控制电脑的需求也越来越大。远程控制电脑技术能够让用户在不同地点的电脑之间进行操作和访问&#xff0c;能够提高工作效率。可以远程控制电脑桌面的软件有哪些&#xff1f; 1. 远程监控电脑软件 需要安装在被控制端电脑&#xff…

【cppcheck 静态代码分析工具使用教程】

cppcheck 是一个流行的静态代码分析工具,用于 C 和 C++ 程序。它可以帮助检测代码中的错误、未定义的行为、内存泄漏等。在 Ubuntu 系统上使用 cppcheck 的基本步骤和示例如下: 安装 cppcheck 打开终端。使用以下命令安装 cppcheck:sudo apt-get update sudo apt-get insta…

linux -系统通用命令查询

有时候内网环境下&#xff0c;系统有些命令没有安装因此掌握一些通用的linux 命令也可以帮助我们解决一些问题查看 1.查看系统内核版本 uname -r2.查看系统版本 cat /etc/os-release3. 查看cpu 配置 lscpu4.查看内存信息 free [参数] 中各个数值的解释如下表 数值解释t…

4.并发中的各种锁概念

目录 概述锁分类按上锁方式划分按特性划分悲观锁/乐观锁重入锁/不可重入锁公平锁/非公平锁独享锁/共享锁 其它自旋锁分段锁无锁/偏向锁/轻量级锁/重量级锁 结束 概述 java 锁分类&#xff0c;虽是概念&#xff0c;很常见。 锁分类 按上锁方式划分 锁关键字解释隐式锁synchr…

提高工作效率的宝藏网站和宝藏工具(高级版)

一、参考资料 亲测&#xff1a;你这些网站都不知道&#xff0c;哪来时间去摸鱼&#xff1f; 提高工作效率的宝藏网站和宝藏工具&#xff08;基础版&#xff09; 二、好用的网站 HelloGitHub - 开源项目平台 HelloGitHub 是一个分享有趣、 入门级开源项目的平台。 希望大家能…

MySQL-02-InnoDB存储引擎

实际的业务系统开发中&#xff0c;使用MySQL数据库&#xff0c;我们使用最多的当然是支持事务并发的InnoDB存储引擎的这种表结构&#xff0c;下面我们介绍下InnoDB存储引擎相关的知识点。 1-Innodb体系架构 InnoDB存储引擎有多个内存块&#xff0c;可以认为这些内存块组成了一…

qgis添加arcgis的mapserver

左侧浏览器-ArcGIS地图服务器-右键-新建连接 Folder: / 展开-双击图层即可

oracle 表树形结构查询递归查询

简介&#xff1a; WITH RECURSIVE 是一种在关系型数据库中处理递归查询的语法。 举例&#xff1a; 假设我们有一个树形结构数据表 tree_table&#xff0c; 包含节点的 ID、父节点的 ID 和节点名称等字段。 示例表数据&#xff1a; --------------- | id | pid | name | ----…

物联网AI MicroPython学习之语法 I2S音频总线接口

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; I2S 介绍 模块功能: I2S音频总线驱动模块 接口说明 I2S - 构建I2S对象 函数原型&#xff1a;I2S(id, sck, ws, sd, mode, bits, format, rate, ibuf)参数说明&#xff1a; 参数类型必选参数&#xff1f…

关于接口测试自动化的总结与思考!

序 近期看到阿里云性能测试 PTS 接口测试开启免费公测&#xff0c;本着以和大家交流如何实现高效的接口测试为出发点&#xff0c;本文包含了我在接口测试领域的一些方法和心得&#xff0c;希望大家一起讨论和分享&#xff0c;内容包括但不仅限于&#xff1a; 服务端接口测试介…

Vatee万腾的科技冒险:vatee创新力量的前沿发现

在当今飞速发展的科技潮流中&#xff0c;Vatee万腾以其独特的创新力量成为前沿的引领者。这场科技冒险不仅仅是技术的迭代&#xff0c;更是一次前所未有的前沿发现之旅&#xff0c;让我们一同深入探索Vatee万腾的科技冒险&#xff0c;感受vatee创新力量的前沿奇迹。 Vatee万腾将…