Postgres中的锁

postgres开发实践中遇到一个问题:

1) A用户在执行一条语句

2) B用户执行语句查询相同的表

会发现B用户始终处于等待状态.

跟踪会发现A进程等待时进程堆栈如下:

#0  LockAcquire (locktag=0x7fffa3ad28f0, lockmode=1, sessionLock=0 ‘\000‘, dontWait=0 ‘\000‘) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lock.c:677
#1  0x0000000000799654 in LockRelationOid (relid=57432, lockmode=1) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lmgr.c:79
#2  0x0000000000531ba1 in RangeVarGetRelidExtended (relation=0xe71da0, lockmode=1, missing_ok=1 ‘\001‘, nowait=0 ‘\000‘, callback=0x0, callback_arg=0x0)
   at /home/hl/uda/build/../collocated_join/src/backend/catalog/namespace.c:377
#3  0x00000000004ab49b in relation_openrv_extended (relation=0xe71da0, lockmode=1, missing_ok=1 ‘\001‘) at /home/hl/uda/build/../collocated_join/src/backend/access/heap/heapam.c:1141
#4  0x00000000004ab759 in heap_openrv_extended (relation=0xe71da0, lockmode=1, missing_ok=1 ‘\001‘) at /home/hl/uda/build/../collocated_join/src/backend/access/heap/heapam.c:1247
#5  0x00000000005a1b2b in parserOpenTable (pstate=0xe72040, relation=0xe71da0, lockmode=1) at /home/hl/uda/build/../collocated_join/src/backend/parser/parse_relation.c:956
#6  0x00000000005a1d7b in addRangeTableEntry (pstate=0xe72040, relation=0xe71da0, alias=0xe71df8, inh=1 ‘\001‘, inFromCl=1 ‘\001‘)
   at /home/hl/uda/build/../collocated_join/src/backend/parser/parse_relation.c:1022
#7  0x000000000058b232 in transformTableEntry (pstate=0xe72040, r=0xe71da0) at /home/hl/uda/build/../collocated_join/src/backend/parser/parse_clause.c:429
#8  0x000000000058b625 in transformFromClauseItem (pstate=0xe72040, n=0xe71da0, top_rte=0x7fffa3ad2d38, top_rti=0x7fffa3ad2d34, namespace=0x7fffa3ad2d28)
   at /home/hl/uda/build/../collocated_join/src/backend/parser/parse_clause.c:640
#9  0x000000000058ab76 in transformFromClause (pstate=0xe72040, frmList=0xe71e58) at /home/hl/uda/build/../collocated_join/src/backend/parser/parse_clause.c:120
#10 0x000000000055a7a3 in transformSelectStmt (pstate=0xe72040, stmt=0xe71e90) at /home/hl/uda/build/../collocated_join/src/backend/parser/analyze.c:939

B进程堆栈如下:

#0  0x00007f110753d627 in semop () from /lib64/libc.so.6
#1  0x0000000000740f01 in PGSemaphoreLock (sema=0x7f11070313f0, interruptOK=1 ‘\001‘) at pg_sema.c:421
#2  0x00000000007a2521 in ProcSleep (locallock=0xddec58, lockMethodTable=0xa7c2c0 <default_lockmethod>) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/proc.c:1134
#3  0x000000000079c6b9 in WaitOnLock (locallock=0xddec58, owner=0xe9a4a8) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lock.c:1623
#4  0x000000000079b57b in LockAcquireExtended (locktag=0x7fffa3ad2130, lockmode=8, sessionLock=0 ‘\000‘, dontWait=0 ‘\000‘, reportMemoryError=1 ‘\001‘)
   at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lock.c:987
#5  0x000000000079ac15 in LockAcquire (locktag=0x7fffa3ad2130, lockmode=8, sessionLock=0 ‘\000‘, dontWait=0 ‘\000‘) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lock.c:677
#6  0x0000000000799654 in LockRelationOid (relid=57432, lockmode=8) at /home/hl/uda/build/../collocated_join/src/backend/storage/lmgr/lmgr.c:79
#7  0x00000000004ab2a5 in relation_open (relationId=57432, lockmode=8) at /home/hl/uda/build/../collocated_join/src/backend/access/heap/heapam.c:1023
#8  0x00000000004ab54c in heap_open (relationId=57432, lockmode=8) at /home/hl/uda/build/../collocated_join/src/backend/access/heap/heapam.c:1189
#9  0x000000000062f0d3 in GetPartitionKeyInfo (pkrelid=57432, attnum=0x7fffa3ad2256, attRangeTypeId=0x7fffa3ad2250) at /home/hl/uda/build/../collocated_join/src/backend/commands/logictablecmds.c:201
#10 0x000000000073d28c in HitForeignTableByCond (rel=0xf76380, rte=0xeb6cb8, ftable=0xf77610, fserver=0xf77940, cond=0xf775d8, oldContext=0xe9a390)
   at /home/hl/uda/build/../collocated_join/src/backend/optimizer/route/createroute.c:599
#11 0x000000000073d721 in build_foreign_route (rel=0xf76380, rte=0xeb6cb8, cond=0xf775d8) at /home/hl/uda/build/../collocated_join/src/backend/optimizer/route/createroute.c:698
#12 0x00000000006ec7bb in set_foreign_size (root=0xeb6648, rel=0xf76380, rte=0xeb6cb8) at /home/hl/uda/build/../collocated_join/src/backend/optimizer/path/allpaths.c:415
#13 0x00000000006ec4e2 in set_rel_size (root=0xeb6648, rel=0xf76380, rti=2, rte=0xeb6cb8) at /home/hl/uda/build/../collocated_join/src/backend/optimizer/path/allpaths.c:250
#14 0x00000000006ecc33 in set_append_rel_size (root=0xeb6648, rel=0xf75d30, rti=1, rte=0xea56a8) at /home/hl/uda/build/../collocated_join/src/backend/optimizer/path/allpaths.c:623
#15 0x00000000006ec49f in set_rel_size (root=0xeb6648, rel=0xf75d30, rti=1, rte=0xea56a8) at /home/hl/uda/build/../collocated_join/src/backend/optimizer/path/allpaths.c:240

导致这个现象的原因是因为在我们在 解析parse的时候就开始加锁了, 直到portal执行完才将此锁释放。而且用的还是exclusive锁。所以

会导致另外的用户查询不了,解决的方法就是把锁的级别改成读锁。

pg中锁分为不同的等级:

#define NoLock                                        0

#define AccessShareLock                        1                /* SELECT */
#define RowShareLock                        2                /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock                3                /* INSERT, UPDATE, DELETE */
#define ShareUpdateExclusiveLock 4                /* VACUUM (non-FULL),ANALYZE, CREATE
                                                                                * INDEX CONCURRENTLY */
#define ShareLock                                5                /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock        6                /* like EXCLUSIVE MODE, but allows ROW
                                                                                * SHARE */
#define ExclusiveLock                        7                /* blocks ROW SHARE/SELECT...FOR
                                                                                * UPDATE */
#define AccessExclusiveLock                8                /* ALTER TABLE, DROP TABLE, VACUUM
                                                                                * FULL, and unqualified LOCK TABLE */

AccessExclusiveLock 这种级别的锁是为了修改而加的。 等级最低,必须等所有锁释放之后才能操作, 查询时用这个锁就会卡住

可以通过 pg_locks 表来查看锁
postgres=# select * from pg_locks where relation = 57432;
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-----+-----------------+---------+----------
relation | 12652 | 57432 | | | | | | | | 2/24 | 674 | AccessShareLock | t | t

时间: 2024-10-11 23:07:51

Postgres中的锁的相关文章

Mysql中那些锁机制之InnoDB

我们知道mysql在曾经.存储引擎默认是MyISAM.可是随着对事务和并发的要求越来越高,便引入了InnoDB引擎.它具有支持事务安全等一系列特性. InnoDB锁模式 InnoDB实现了两种类型的行锁. 共享锁(S):同意一个事务去读一行,阻止其它事务获得同样的数据集的排他锁. 排他锁(X):同意获得排他锁的事务更新数据,可是组织其它事务获得同样数据集的共享锁和排他锁. 能够这么理解: 共享锁就是我读的时候,你能够读,可是不能写.排他锁就是我写的时候.你不能读也不能写.事实上就是MyISAM的

Innodb中的锁

虽然比较擅长的是Oracle,但是公司使用的是MySQL数据库,所以不得不对MySQL数据库多研究一下.今天就谈一下MySQL中的锁. 谈锁之前,要明白为什么会有锁这种东西.之所以有锁,大部分情况下是为了实现事务(transaction)之间的隔离,那么事务之间有几种隔离方式,各种隔离方式又是为了达到什么效果呢?先来说一下各种读现象. 脏读:即一个事务A读取了事务B还没有提交过的数据: 不可重复读:即事务A在第一次按照某条SQL语句读取后跟第二次按照相同的SQL语句读取数据库,这段时间内,事务B

c#语言-多线程中的锁系统

介绍 平常在多线程开发中,总避免不了线程同步.这次就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. 3:字符串锁. 二: mutex 三:Semaphore 四:总结 一:lock.Monitor 1:基础 Lock是Monitor语法糖简化写法.Lock在IL会生成Monitor. //======Example 1===== string obj = "helloworld"; lock (obj) { Console.Wri

十一、JUC包中的锁

JUC,即java.util.concurrent. 悲观锁和乐观锁 悲观锁和乐观锁是一种思想. 悲观锁,持有一种悲观的态度,认为会出现很坏的情况,所以,先做预防措施.独占锁是一种悲观锁,synchronized就是一种独占锁. 而乐观锁,则是持有一种持有种乐观的态度,认为不会出现什么问题,有问题了再说. 对于常用多线程编程的人估计知道,在jdk5之前,在多线程编程的时候,为了保证多个线程对一个对象同时进行访问时,我们需要加同步锁synchronized,保证对象的在使用时的正确性,但是加锁的机

Hibernate中的锁机制

锁机制:是数据库为了保证数据的一致性<一个事务的各种操作不相互影响>而使各种共享资源在被并发访问访问变得有序所设计的一种规则,用来保证在当前用户进行操作数据的时候其他的用户不能对同一数据进行任何操作. Hibernate是一个持久层框架,他的操作就是用来存取数据库中的数据,为了保证数据的一致性,hibernate提供了自己的锁机制. Hibernate的锁机制: 乐观锁:<pessimistic locking>他认为一般不会出现多个用户同时操作同一条数据的情况,因此不做资料库层次

sql server中的锁 事务锁 更新锁 保持锁 共享锁 你知道吗?

锁定数据库的一个表 SELECT * FROM table WITH (HOLDLOCK) 注意: 锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除 SELECT 语句中"加锁选项"的功能说明 SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能.用户既能使用SQL Ser

MySQL 温故而知新--Innodb存储引擎中的锁

近期碰到非常多锁问题.所以攻克了后,细致再去阅读了关于锁的书籍,整理例如以下:1,锁的种类 Innodb存储引擎实现了例如以下2种标准的行级锁: ? 共享锁(S lock),同意事务读取一行数据. ?  排它锁(X lock).同意事务删除或者更新一行数据. 当一个事务获取了行r的共享锁.那么另外一个事务也能够马上获取行r的共享锁,由于读取并未改变行r的数据.这样的情况就是锁兼容. 可是假设有事务想获得行r的排它锁,则它必须等待事务释放行r上的共享锁-这样的情况就是锁不兼容.二者兼容性例如以下表

java 多线程中的锁的类别及使用

目前在Java中存在两种锁机制: synchronized Lock Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea. 数据同步需要依赖锁,那锁的同步又依赖谁? synchronized给出的答案是在软件层面依赖JVM, 而Lock给出的方案是在硬件层面依赖特殊的CPU指令 Synchronized 其应用层的语义是可以把任何一个非null对象作为"锁" 当synchronized作用在方法上时,锁住的便是对象实例(this): 当作用在静态方法

【转载】Java中的锁机制 synchronized &amp; Lock

参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理. 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的