[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.hqwc.cn/news/215610.html

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

相关文章

nodejs+vue+python+PHP+微信小程序-青云商场管理系统的设计与实现-安卓-计算机毕业设计

研究步骤、措施&#xff1a; &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&#xff09;做需求分析及功能模块划分&#xff1b; &#xff08;3&#xff09;指导老师通过后&#xff0c;设计出用例图&#xff0c;E-R图&#xff0c;功能模块图 …

爬虫项目实战:利用基于selenium框架的爬虫模板爬取豆瓣电影Top250

&#x1f44b; Hi, I’m 货又星&#x1f440; I’m interested in …&#x1f331; I’m currently learning …&#x1f49e; I’m looking to collaborate on …&#x1f4eb; How to reach me … README 目录&#xff08;持续更新中&#xff09; 各种错误处理、爬虫实战及模…

80C51单片机----数据传送类指令

目录 一.一般传送指令&#xff0c;即mov指令 1.16位传送&#xff08;仅1条&#xff09; 2.8位传送 &#xff08;1&#xff09;目的字节为A&#xff08;累加器&#xff09; &#xff08;2&#xff09;目的字节为Rn(工作寄存器) &#xff08;3&#xff09;目的字节为direct…

Python报错:AttributeError(类属性、实例属性)

Python报错&#xff1a;AttributeError&#xff08;类属性、实例属性&#xff09; Python报错&#xff1a;AttributeError 这个错误就是说python找不到对应的对象的属性&#xff0c;百度后才发现竟然是初始化类的时候函数名写错了 __init__应该有2条下划线&#xff0c;如果只有…

逆矩阵相关性质与例题

1.方阵的行列式&#xff1a;就是将方阵中的每一个元素转换至行列式中。 1.性质一&#xff1a;转置方阵的行列式等于转置前的行列式。&#xff08;对标性质&#xff1a;行列式与它的转置行列式相等&#xff09; 2.性质二&#xff1a;|ka||a|*k的n次方&#xff0c;n为方阵阶数。 …

Feign接口请求返回异常 no suitable HttpMessageConvert found for response type

问题场景&#xff1a; 后端调用feign接口请求, 接口返回异常, no suitable HttpMessageConvert found for response type 问题描述 报错异常如下&#xff1a; //根据图片特征 去查询人员信息ResultVo<List> personVos ipbdFaceLibPersonApi.queryFacePersonByFeatur…

ErphpdownV16.21插件 安装教程和插件下载

ErphpdownV16.21插件下载_新版本 上传插件并解压 登入后台插件管理启动ErphpdownV16.21插件即可 启动后设置即可使用此版本为学习版插件 功能介绍&#xff1a; Erphpdown会员推广下载专业版 经过完美测试运行于wordpress 3.x-6.x版本。后续会增加更多实用的功能。已针对此插件…

Javaweb之前端工程化的详细解析

3 前端工程化 3.1 前端工程化介绍 我们目前的前端开发中&#xff0c;当我们需要使用一些资源时&#xff0c;例如&#xff1a;vue.js&#xff0c;和axios.js文件&#xff0c;都是直接再工程中导入的&#xff0c;如下图所示&#xff1a; 但是上述开发模式存在如下问题&#xff…

物联网AI MicroPython学习之语法 实时时钟RTC

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; RTC 介绍 模块功能: 实时时钟RTC驱动模块 接口说明 RTC - 构建RTC对象 函数原型&#xff1a;RTC()参数说明&#xff1a; 无 返回值&#xff1a; 构建的RTC对象。 datetime - RTC时钟操作 函数原型&a…

导入PIL时报错

在导入PIL时,报以下错误: 查找原因 参考博客 Could not find a version that satisfies the requirement PIL (from versions: ) No matching distributi-CSDN博客,按照wheel后,安装PIL时,报如下的错误。 查找说是python版本与wheel文件版本不同,确认本机python版本 …

【深度学习】卷积神经网络结构组成与解释

卷积神经网络是以卷积层为主的深度网路结构&#xff0c;网络结构包括有卷积层、激活层、BN层、池化层、FC层、损失层等。卷积操作是对图像和滤波矩阵做内积&#xff08;元素相乘再求和&#xff09;的操作。 1. 卷积层 常见的卷积操作如下&#xff1a; 卷积操作解释图解标准卷…

Oracle SQL 注入上的 Django GIS 函数和聚合漏洞 (CVE-2020-9402)

漏洞描述 Django 于2020年3 月4日发布了一个安全更新&#xff0c;修复了 GIS 函数和聚合中的 SQL 注入漏洞。 参考链接&#xff1a; Django security releases issued: 3.0.4, 2.2.11, and 1.11.29 | Weblog | Django 该漏洞要求开发者使用 JSONField/HStoreField;此外&…