https://www.postgresql.org/docs/13/explicit-locking.html#LOCKING-ROWS
表级锁
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE | 持锁语句 | 描述 | |
---|---|---|---|---|---|---|---|---|---|---|
ACCESS SHARE | × | SELECT | 一般对表的读操作都会获得这个模式的锁 | |||||||
ROW SHARE | × | × | SELECT FOR UPDATE SELECT FOR SHARE | |||||||
ROW EXCLUSIVE | × | × | × | × | INSERT/UPDATE/DELETE | 一般对表的写操作都会获得这个模式的锁 | ||||
SHARE UPDATE EXCLUSIVE | × | × | × | × | × | VACUUM( not FULL ) / ANALYZE / | 避免concurrent schema changes和VACUUM. | |||
SHARE | × | × | × | × | × | CREATE INDEX(not CURRENTLY) | 避免concurrent data changes | |||
SHARE ROW EXCLUSIVE | × | × | × | × | × | × | CREATE TRIGGER ALTER TABLE | 避免concurrent data changes,并且是self-exclusive的,同一时间只能有一个session持有该锁 | ||
EXCLUSIVE | × | × | × | × | × | × | × | REFRESH MATERIALIZED VIEW | ||
ACCESS EXCLUSIVE | × | × | × | × | × | × | × | × | DROP TABLE / TRUNCATE / REINDEX / CLUSTER / VACUUM FULL / REFRESH MATERIALIZED VIEW (not CONCURRENTLY) | 与其他所有锁都冲突,同一时间只允许一个session持有 ,prevents concurrent transactions from reading and writeing |
行级锁
FOR UPDATE | FOR NO KEY UPDATE | FOR SHARE | FOR KEY SHARE | 持锁语句 | |
---|---|---|---|---|---|
FOR UPDATE | x | x | x | x | SELECT FOR UPDATE / DELETE / UPDATE |
FOR NO KEY UPDATE | x | x | x | UPDATE / SELECT FOR NO KEY UPDATE | |
FOR SHARE | x | x | SELECT FOR SHARE | ||
FOR KEY SHARE | x | SELECT FOR KEY SHARE |
块/页级锁
页级锁用来控制shared buffer pool中页块的读写操作。当一行被fetched或updated之后,这些锁立即释放。
死锁
PostgreSQL 自动检测死锁,并中断造成死锁的其中一个事务,使得另一个事务得以提交。
哪个事务将会被中断并没用固定的规则去判定。
避免死锁发生的最佳方法是在应用层获取多个对象的锁时,保持相同的顺序。
Advisory locks
应用程序控制的锁。可以在会话级别和事务级别获取咨询锁,并在会话结束或事务完成时按预期释放。
当程序进程启动时,你可以通过 Postgres 获取一个锁,然后在程序退出时释放它。
这样,我们就保证了程序不能并发运行,因为它在启动时无法获取锁。
Advisory lock并不会对数据库对象加锁,不影响数据库对象的CRUD操作。
应用场景:
协调对一些共享资源或第三方服务的访问,需要保证在一个时间内只能有一个访问。
统计并发送报告,需要保证没有其他人同时进行统计计算。
多节点任务调度器协调任务分配