1

PG基础篇--逻辑结构管理(锁机制)

 2 years ago
source link: https://blog.51cto.com/u_13874232/5454205
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

行锁只有共享锁和排它锁,pg不称读锁的原因是由于有多版本的实现,实际读取数据时,并不会在行上执行任何锁

死锁发生的四个必要条件

(1)互斥条件:指事务对所分配到的资源加了排它锁,即在一段时间内只能由一个事务加锁占用,如果此时还有其他进程进行排它锁,则请求者只能等待,直至持有排它锁的事务释放排它锁。

(2)请求和保持条件:指事务已经至少持有了一把排它锁,但又提出了新的排它锁请求,而该资源上的排它锁已被其他事务占有,此时请求被阻塞,但同时它对自己已获得的排它锁又持有不放。

(3)不剥夺条件:指事务已获得在未使用完之前不能被其他进程剥夺,只能在使用完时由自己释放。

(4)环路等待条件:指发生死锁时,必然存在一个事务--资源的环形链。

表级锁命令LOCK TABLE

LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]

name:表名

lockmode:表级锁级别,共8种

nowait:如果没有该关键字,无法获得锁时会一直等待。而如果加入了nowait关键字,在无法立即获取该锁时,此命令会立即退出并报错。

在PG中自己持有的锁是从不冲突的。

行级锁命令

select  for  {update|share}  [of table_name,[],.....]   [nowait]

nowait和表级锁使用含义相同

查看一个事务产生了哪些锁,哪个事务被哪个事务阻塞了,通过查询系统视图pg_locks来得到。

Column | Type | Collation | Nullable | Default
--------------------+----------+-----------+----------+---------
locktype | text | | |
database | oid | | |
relation | oid | | |
page | integer | | |
tuple | smallint | | |
virtualxid | text | | |
transactionid | xid | | |
classid | oid | | |
objid | oid | | |
objsubid | smallint | | |
virtualtransaction | text | | |
pid | integer | | |
mode | text | | |
granted | boolean | | |
fastpath | boolean | | |

transactionid代表事务ID,简写XID,virtualxid代表虚拟事务ID VXID。对于只读事务,分配VXID,不需要实际分配一个真实的事务ID。

virtualtransaction之前的字段(不包含virtualtransaction)用于描述锁定对象信息,之后的部分用于描述持有锁或等待锁session信息。

postgres=# select * from pg_locks where pid in (27089,28137);
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-------+---------------------+---------+----------
relation | 13593 | 12143 | | | | | | | | 3/131409 | 27089 | AccessShareLock | t | t
virtualxid | | | | | 3/131409 | | | | | 3/131409 | 27089 | ExclusiveLock | t | t
virtualxid | | | | | 4/4750 | | | | | 4/4750 | 28137 | ExclusiveLock | t | t
relation | 13593 | 16526 | | | | | | | | 3/131409 | 27089 | AccessExclusiveLock | t | f
transactionid | | | | | | 6546 | | | | 4/4750 | 28137 | ExclusiveLock | t | f
transactionid | | | | | | 6544 | | | | 3/131409 | 27089 | ExclusiveLock | t | f
relation | 13593 | 16526 | | | | | | | | 4/4750 | 28137 | AccessExclusiveLock | f | f
(7 rows)

granted为t表示持有该锁,为f表示没有获得这把锁,从而被阻塞。

所有,如果需要查看被阻塞的进程,只需要查询视图pg_locks中granted为f的进程就可以了。

同样行锁查询该视图通过pg_locks中的transactionid的锁信息就可以了。

select locktype,
relation::reglcass as rel,
page||','||tuple as ctid,
virtualxid as vxid,
transactionid as xid,
virtualtransaction as vxid2,
pid,mode,granted from pg_locks where pid in (8453,8764);

select * from testtab-1 where ctid='(0,1)';

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK