greenplum采用了postgresql的锁机制,对于表,有以下几种锁及互斥机制:
两个事务在同一时刻不能在同一个表上持有属于相互冲突模式的锁(但是,一个事务决不会和自身冲突。例如,它可以在同一个表上获得ACCESS EXCLUSIVE锁然后接着获取ACCESS SHARE锁)。非冲突锁模式可以由许多事务同时持有。请特别注意有些锁模式是自冲突的(例如,在一个时刻ACCESS EXCLUSIVE锁不能被多于一个事务持有),而其他锁模式不是自冲突的(例如,ACCESS SHARE锁可以被多个事务持有)。
对于这些锁的详细解释,可参考:https://blog.csdn.net/hmxz2nn/article/details/82795231
视图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 视图提供了有关在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等列。
该视图显示了当前所有表上持有锁,以及查询关联的锁的相关联的会话信息。该视图能够被所有用户访问,但是非超级用户只能够看到他们有权限访问的关系上持有的锁。
列 | 描述 |
---|---|
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