Greenplum死锁定位解决

锁机制

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

管理锁的视图

pg_stat_activity

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

名称 类型 描述
datid oid 数据库OID
datname name 数据库名称
procpid integer 服务进程的进程ID
sess_id integer 会话ID
usesysid oid 角色ID
usename name 角色名
current_query text 进程正在执行的当前查询
waiting boolean 如果正等待一个锁则为真,否则为假
query_start timestamptz 查询开始执行的时间
backend_start timestamptz 后台进程开始的时间
client_addr inet 客户端地址
client_port integer 客户端端口
application_name text 客户端应用名
xact_start timestamptz 事务开始时间
waiting_reason text 服务进程正在等待的原因。值可以是:lock或replication

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

pg_locks

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

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

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

类型 描述
locktype text 可锁对象的类型:relation, extend, page, tuple, transactionid, object, userlock, resource queue, 或 advisory
database oid 该对象存在的数据库的Oid, 如果该对象是共享对象,则为0。如果对象是事务ID,则为空。
relation oid 关系的Oid,如果对象不是关系或者关系的一部分,则为NULL。
page integer 关系中的页码,如果对象不是元组或者关系页则为NULL
tuple smallint 页中的元组号,如果该对象不是个元组则为NULL。
transactionid xid 事务的Id,如果该对象不是一个事务Id,则为NULL。
classid oid 包含对象的系统目录的Oid,如果对象不是一般数据库对象,则为NULL。
objid oid 其系统目录中对象的Oid,如果对象不是一般数据库对象,则为NULL。
objsubid smallint 对一个表列来说, 这是列号( classid和objid引用表本身)。 对于所有其他的对象类型,此列为0。如果对象不是数据库对象,则为NULL。
transaction xid 等待或持有该锁的事务的Id。
pid integer 持有或等待该锁的事务进程的进程Id,如果锁由准备(prepared)的事务持有,则为NULL。
mode text 该进程所持有或期望的锁模式的名称。
granted boolean 锁被持有为真,锁为等待为假。
mppsessionid integer 与锁相关的客户端会话的id。
mppiswriter boolean 指明该锁是否由一个写进程所持有。
gp_segment_id integer 该 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

你可能感兴趣的:(GreenPlum,greenplum死锁)