查看pg中的锁

要查看pg中的锁,需要查看pg_locks这个视图

Table 42-37. pg_locks 字段

名字 类型 引用 描述
locktype text   可锁定对象的类型: relationextendpagetupletransactionidobject, 或者 userlock
database oid pg_database.oid 对象所在的数据库的 OID,如果对象是共享对象, 那么就是零,如果对象是一个事务 ID,就是 NULL。
relation oid pg_class.oid 关系的 OID,如果对象不是关系,也不是关系的一部分,则为 NULL
page integer   关系内部的页面编号,如果对象不是元组页不是关系页,则为 NULL
tuple smallint   页面里面的元组编号,如果对象不是元组,则为 NULL
transactionid xid   事务的 ID,如果对象不是事务 ID,就是 NULL
classid oid pg_class.oid 包含该对象的系统表的 OID,如果对象不是普通数据库对象,则为 NULL
objid oid 任何 OID 字段 对象在其系统表内的 OID,如果对象不是普通数据库对象,则为 NULL
objsubid smallint   对于表的一个字段,这是字段编号(classid 和 objid 指向表自身)。 对于其它对象类型,这个字段是零。如果这个对象不是普通数据库对象,则为 NULL
transaction xid   持有此锁或者在等待此锁的事务的 ID。
pid integer   持有或者等待这个锁的服务器进程的进程 ID。  如果锁是被一个准备好的事务持有的,那么为空(null)。
mode text   这个进程持有的或者是期望的锁模式(参阅 Section 12.3.1)
granted boolean   如果持有锁,为真,如果等待锁,为假

virtualxid:虚拟事务id,每次生成一个事务,会在pg_clog下的commit log 文件中占用2bit空间,因为有些事务中没有实际的 操作数据的语句,所以这种分配事务id有些浪费空间了,于是提出了虚拟事务的概念,主要是为了节省空间。在mysql中针对只读事务是有优化的,只读事务是没有分配事务id的。

下面开2个session看下锁的情况

A:

select pg_backend_pid();

9972

创建个表并lock

create table t(id integer);
insert into t values(1);




begin;
lock table t;

B:

select * from pg_locks where pid=9972;


看到xid是空的,没有实际事务,granted是t,表示持有锁,在b中也试图lock表看下情况

begin;
lock table t;

一直提示查询运行中,被阻塞了,在A中查看下锁的信息


看到10732,也就是B回话的granted是f,也就是在发起请求获得锁,同时对于B也有virtualxid的exclusiveLock锁,就是对于事务id加了锁

在A提交后,B就获得了锁,但是在A提交后,新开个窗口C,在查询pg_locks视图,看到这个C的会话对t表有共享锁,这个就不太明白了,明明是已经提交了事务,并且C中没有操作t表,不知道为什么了



在A中对行操作,看下行锁是什么样的情况

A:

begin;


update t set id=5;


看到事务中有了行排他锁出现,并且出现了transactionid并且xid是625的行,说明这个是有实际数据操作的事务

在B中也更新下行,看下情况
begin;
update t set id=10;

出现了阻塞,看下视图的情况


看到10732这个会话被阻塞了,要申请的锁是transactionid625这个锁,在最后看到625这个锁是被9972占用了,要查看那个记录被占用了

select locktype,relation::regclass as rel,page||','||tuple as ctid,virtualxid as vxid,transactionid as xid,virtualtransaction as vxid2,pid,mode,granted from pg_locks;


select * from t where ctid='(0,4)';

看到是t表中id=4的记录导致阻塞


你可能感兴趣的:(PostgreSQL管理)