Greenplum死锁定位解决

锁机制

greenplum采用了postgresql的锁机制,对于表,有以下几种锁及互斥机制:
在这里插入图片描述
两个事务在同一时刻不能在同一个表上持有属于相互冲突模式的锁(但是,一个事务决不会和自身冲突。例如,它可以在同一个表上获得ACCESS EXCLUSIVE锁然后接着获取ACCESS SHARE锁)。非冲突锁模式可以由许多事务同时持有。请特别注意有些锁模式是自冲突的(例如,在一个时刻ACCESS EXCLUSIVE锁不能被多于一个事务持有),而其他锁模式不是自冲突的(例如,ACCESS SHARE锁可以被多个事务持有)。
对于这些锁的详细解释,可参考:https://blog.csdn.net/hmxz2nn/article/details/82795231

管理锁的视图
pg_stat_activity

视图pg_stat_activity每行显示一个服务器进程同时详细描述与之关联的用户会话和查询。只有在检查视图的用户是超级用户或者是正在报告的进程的拥有者时,这些列才可见。

名称类型描述
datidoid数据库OID
datnamename数据库名称
procpidinteger服务进程的进程ID
sess_idinteger会话ID
usesysidoid角色ID
usenamename角色名
current_querytext进程正在执行的当前查询
waitingboolean如果正等待一个锁则为真,否则为假
query_starttimestamptz查询开始执行的时间
backend_starttimestamptz后台进程开始的时间
client_addrinet客户端地址
client_portinteger客户端端口
application_nametext客户端应用名
xact_starttimestamptz事务开始时间
waiting_reasontext服务进程正在等待的原因。值可以是:lock或replication

重点关注procpid,current_query,waiting,waiting_reason等列。

pg_locks

pg_locks 视图提供了有关在Greenplum数据库中由开放事务持有的锁的信息的访问。

pg_locks 包含一行关于每个积极可锁对象,请求的锁模式和相关事务。 因此,如果多个事务正在持有或等待其上的锁,同样的可锁对象可能会出现多次。 但是,目前没有锁的对象根本就不会出现。

有几种不同类型的可锁对象:整个关系(如表),关系的个别页,关系的个别元组,事务Id和通用数据库对象。另外,扩展关系的权利表示为单独的可锁对象。

类型描述
locktypetext可锁对象的类型:relation, extend, page, tuple, transactionid, object, userlock, resource queue, 或 advisory
databaseoid该对象存在的数据库的Oid, 如果该对象是共享对象,则为0。如果对象是事务ID,则为空。
relationoid关系的Oid,如果对象不是关系或者关系的一部分,则为NULL。
pageinteger关系中的页码,如果对象不是元组或者关系页则为NULL
tuplesmallint页中的元组号,如果该对象不是个元组则为NULL。
transactionidxid事务的Id,如果该对象不是一个事务Id,则为NULL。
classidoid包含对象的系统目录的Oid,如果对象不是一般数据库对象,则为NULL。
objidoid其系统目录中对象的Oid,如果对象不是一般数据库对象,则为NULL。
objsubidsmallint对一个表列来说, 这是列号( classid和objid引用表本身)。 对于所有其他的对象类型,此列为0。如果对象不是数据库对象,则为NULL。
transactionxid等待或持有该锁的事务的Id。
pidinteger持有或等待该锁的事务进程的进程Id,如果锁由准备(prepared)的事务持有,则为NULL。
modetext该进程所持有或期望的锁模式的名称。
grantedboolean锁被持有为真,锁为等待为假。
mppsessionidinteger与锁相关的客户端会话的id。
mppiswriterboolean指明该锁是否由一个写进程所持有。
gp_segment_idinteger该 Greenplum 持有该锁的段的id(dbid)

重点关注pid,mode,granted等列。

gp_toolkit.gp_locks_on_relation

该视图显示了当前所有表上持有锁,以及查询关联的锁的相关联的会话信息。该视图能够被所有用户访问,但是非超级用户只能够看到他们有权限访问的关系上持有的锁。

描述
lorlocktype能够加锁对象的类型:relation、 extend、page、tuple、transactionid、object、userlock、resource queue以及advisory
lordatabase对象存在的数据库对象ID,如果对象为一个共享对象则该值为0。
lorrelname关系名。
lorrelation关系对象ID。
lortransaction锁所影响的事务ID 。
lorpid持有或者等待该锁的服务器端进程的进程ID 。如果该锁被一个预备事务持有则为NULL。
lormode由该进程持有或者要求的锁模式名。
lorgranted显示是否该锁被授予(true)或者未被授予(false)。
lorcurrentquery会话中的当前查询。
死锁原因排查

1.从 pg_stat_activity 视图中查找处于等锁状态的任务:

select * from pg_stat_activity where waiting_reason='lock';

比如说找到那张表相关的任务正在处于锁定状态。
2.关联pg_locks,pg_class,pg_stat_activity 表,查询与上述任务相关的锁。
假设表test_table相关的任务处于锁定状态。

select a.locktype,a.pid,a.gp_segment_id,b.relname,substring(c.current_query,1,100),
c.xact_start,a.pid,a.mode,a.granted from pg_locks a,pg_class b,pg_stat_activity c 
where a.relation = b.oid and a.pid = c.procpid and b.relname like '%test_table%';

也可以通过视图gp_toolkit.gp_locks_on_relation进行查询。

select * from gp_toolkit.gp_locks_on_relation where lorrelname like '%test_table%';

从而获取到那些表之间那些锁发生了冲突,导致了死锁。
也可以通过搜索进程号,来判断死锁情况。

补充:有时候一些死锁发生在master节点和segment节点的任务上,在排查该死锁时。可以通过修改gp_toolkit.gp_locks_on_relation创建新的视图,并在所有节点上运行该视图,统计log信息,定位死锁。

死锁问题解决

找到死锁的原因后,可以终止其中的某个事务,将锁释放,从而解决死锁。
命令为:

select pg_terminate_backend(procpid);

参考:
1.https://gp-docs-cn.github.io/docs/
2.https://blog.csdn.net/icycode/article/details/78827999

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值