postgres 锁表的模式

本文介绍了PostgreSQL中不同类型的锁模式及其应用场景。包括ACCESSEXCLUSIVEMODE、EXCLUSIVEMODE等,并通过对比解释了ROWEXCLUSIVEMODE的实际效果与预期之间的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ACCESS SHARE MODE 
ROW SHARE MODE 
ROW EXCLUSIVE MODE 
SHARE UPDATE EXCLUSIVE MODE 
SHARE MODE 
SHARE ROW EXCLUSIVE MODE 
EXCLUSIVE MODE 
ACCESS EXCLUSIVE MODE 

可看一看 http://www.phpchina.com/manual/PostgreSQL/sql-lock.html 


的说明。 
太复杂了 

简单的说一下 
如果你什么都不写,只是lock table xxx;那么就是ACCESS EXCLUSIVE MODE,是最高级的锁,会和其他读冲突.在锁成功之前,其他事务的读操作都要结束才行。 

一般都是用lock table xxx in EXCLUSIVE MODE,锁之前你读可以,锁之后别人读可以,写不行。 

   row exclusive mode经过实验,好像并没有锁住任何行,其他事务还是可以update delete insert,这个行为就和语义不一致了. 
    是否这样理解?row打头的这些,只是在行锁发生时,对表做的一个标记?即一般情况下对一行进行写入,或显式产生一个行锁,会产生一个行锁的同时,也产生一“row exclusive”表锁。而单独执行 lock table in row exclusive mode只是产生“row exclusive”表锁,而实际上不存在一个真正意义的行锁 。

<think>我们正在使用PostgreSQL数据库,并希望检查当前数据库中被定的。根据引用[1]:trace_lock_oidmin (integer)描述:如果设置,则不跟踪此 OID以下的(用于避免在系统上输出)。此参数仅在编译PostgreSQL时定义了LOCK_DEBUG宏时才可用。 [^1]但是,这个参数是用于调试的,通常我们不会使用它。我们更关心的是如何查询当前数据库中的信息。另外,引用[4]提到:PostgreSQL是一个多进程架构的客户端/服务器模式的关系型数据库管理系统。其中backend进程每个客户端对应一个,处理该客户端的请求。信息可以通过查询系统视图来获取。在PostgreSQL中,信息存储在`pg_locks`系统视图中,而的信息存储在`pg_class`系统中。我们可以通过连接这些系统视图来获取被定的的信息。具体步骤:1.查询`pg_locks`视图,获取定的对象(relation类型)的信息。2.关联`pg_class`,获取名。3.关联`pg_stat_activity`视图,可以获取到持有的进程和查询信息。注意:有不同的模式,比如AccessShareLock、ExclusiveLock等。我们可能关心的是排他ExclusiveLock)或者写(RowExclusiveLock)等。以下是一个常用的查询当前数据库中级别的SQL语句: ```sqlSELECTpg_stat_activity.pid,pg_class.relname,pg_locks.mode,pg_locks.granted,pg_stat_activity.query,pg_stat_activity.client_addrFROMpg_locksJOINpg_class ONpg_locks.relation =pg_class.oidJOINpg_stat_activity ONpg_locks.pid =pg_stat_activity.pidWHEREpg_locks.relation ISNOT NULLAND pg_locks.modeNOT LIKE'%Share%' --排除共享,我们通常关心排他ANDpg_class.relkind= 'r'--只关注普通('r'示普通)ORDER BYpg_stat_activity.pid;```但是,请注意:-这个查询可能返回很多行,因为PostgreSQL中很多操作会获取(比如普通的SELECT也会获取AccessShareLock)。 -我们通过`pg_locks.modeNOT LIKE'%Share%'`来排除共享,只显示排他(或更高级别的),这些可能会阻塞其他操作。-如果`granted`字段为false,则示该进程正在等待这个(被阻塞)。另外,也可以使用以下查询来查看所有(包括共享)以及等待情况: ```sqlSELECTblocked.pid ASblocked_pid,blocked_activity.usenameAS blocked_user,blocking.pid ASblocking_pid,blocking_activity.usenameAS blocking_user,blocked_activity.query ASblocked_statement,blocking_activity.query ASblocking_statementFROM pg_catalog.pg_locksblocked_locksJOINpg_catalog.pg_stat_activityblocked_activity ONblocked_activity.pid =blocked_locks.pidJOINpg_catalog.pg_locks blocking_locksON blocking_locks.locktype =blocked_locks.locktypeAND blocking_locks.DATABASE ISNOT DISTINCT FROMblocked_locks.DATABASEAND blocking_locks.relationIS NOTDISTINCTFROM blocked_locks.relationAND blocking_locks.page ISNOT DISTINCT FROMblocked_locks.pageAND blocking_locks.tupleIS NOTDISTINCTFROM blocked_locks.tupleAND blocking_locks.virtualxidIS NOTDISTINCTFROM blocked_locks.virtualxidAND blocking_locks.transactionid ISNOT DISTINCT FROMblocked_locks.transactionidAND blocking_locks.classidIS NOTDISTINCTFROM blocked_locks.classidAND blocking_locks.objid ISNOT DISTINCT FROMblocked_locks.objidAND blocking_locks.objsubidIS NOTDISTINCTFROM blocked_locks.objsubidAND blocking_locks.pid!= blocked_locks.pidJOIN pg_catalog.pg_stat_activity blocking_activityON blocking_activity.pid= blocking_locks.pidWHERENOT blocked_locks.granted;```这个查询可以找出被阻塞的进程以及阻塞它的进程。因此,要检查当前数据库中被定的,我们可以运行上述查询之一。注意:需要具有超级用户权限或者具有访问系统视图的权限。如果只是想查看当前被定的(排除共享),可以使用第一个查询。另外,PostgreSQL还提供了一个函数`pg_blocking_pids(pid)`,可以获取阻塞指定进程的进程ID列。例如:`SELECTpg_blocking_pids(1234);`会返回阻塞进程1234的所有进程ID。根据这些信息,我们可以判断哪些定,以及定它们的进程和查询。最后,如果需要解,可以通过`SELECTpg_cancel_backend(pid);`来取消该进程的查询(不会终止整个进程,只取消当前查询)或者使用`SELECT pg_terminate_backend(pid);`来终止整个进程(谨慎使用)。请根据实际情况选择查询语句。</think>### PostgreSQL 检查当前数据库中被定的PostgreSQL 中检查情况,主要通过查询系统视图实现。以下是详细步骤: #### 1. **查询所有信息** ```sql SELECT * FROM pg_locks; ``` 此视图显示所有对象(、行、事务等)的详细信息[^4]。 #### 2. **定位** ```sql SELECT lock.locktype, relname AS table_name, lock.mode, lock.pid, lock.granted, query AS blocked_query FROM pg_locks lock JOIN pg_class cls ON lock.relation = cls.oid JOIN pg_stat_activity act ON lock.pid = act.pid WHERE locktype = 'relation' AND relname NOT LIKE 'pg_%'; -- 排除系统 ``` **关键字段说明**: - `locktype`:类型(`relation`=) - `table_name`:被名 - `mode`:模式(如 `AccessExclusiveLock` 示排他) - `pid`:持有的进程ID - `granted`:是否已获得(`true`/`false`) - `blocked_query`:正在执行的SQL语句 #### 3. **检查等待(阻塞情况)** ```sql SELECT blocked.pid AS blocked_pid, blocking.pid AS blocking_pid, blocked.query AS blocked_query, blocking.query AS blocking_query FROM pg_locks blocked JOIN pg_locks blocking ON blocking.locktype = blocked.locktype AND blocking.transactionid = blocked.transactionid AND blocking.pid != blocked.pid JOIN pg_stat_activity act_blocked ON blocked.pid = act_blocked.pid JOIN pg_stat_activity act_blocking ON blocking.pid = act_blocking.pid WHERE NOT blocked.granted; ``` 此查询显示哪些进程被阻塞及阻塞源[^4]。 #### 4. **常用模式说明** | 模式 | 描述 | |------------------------|----------------------------------| | `AccessShareLock` | SELECT 产生的共享 | | `RowExclusiveLock` | UPDATE/DELETE 产生的行级排他 | | `ShareUpdateExclusiveLock` | VACUUM 等维护操作 | | **`AccessExclusiveLock`** | DROP/TRUNCATE 等排他(最危险)| #### 5. **解方法** - 终止阻塞进程: ```sql SELECT pg_terminate_backend(pid); -- 替换为实际PID ``` - 避免强制终止:优先检查长时间运行的事务或优化查询 #### 注意事项 1. 需要 `pg_stat_activity` 视图的访问权限(通常需超级用户) 2. 系统(如 `pg_locks`)的可通过 `trace_lock_oidmin` 参数过滤[^1] 3. 排他(如 `AccessExclusiveLock`)会完全阻塞操作 --- ### 相关问题 1. 如何监控 PostgreSQL 中长时间运行的事务? 2. PostgreSQL 等待超时如何配置? 3. 哪些操作会导致级排他(`AccessExclusiveLock`)? 4. 如何避免生产环境中的竞争问题? 5. PostgreSQL 与 MySQL 在机制上有何主要差异?[^2] [^1]: trace_lock_oidmin (integer) 描述:如果设置,则不跟踪此 OID 以下的(用于避免在系统上输出)。此参数仅在编译 PostgreSQL 时定义了 LOCK_DEBUG 宏时才可用。 [^2]: PostgreSQL完全免费,而且是BSD协议,MySQL现在主要是被Oracle公司控制。 [^4]: PostgreSQL是一个多进程架构的客户端/服务器模式的关系型数据库管理系统。包含postgres server进程、backend进程、background进程等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值