📚 目录
🛠️ 概述
在 PostgreSQL 中,锁(Lock) 用于确保多个事务并发访问数据库时,数据的一致性和完整性。锁机制确保在执行某些操作(如更新、删除等)时,其他事务不能同时修改相同的数据。PostgreSQL 提供了多种类型的锁,以便在并发操作中提供不同级别的控制。
🔐 锁的基本类型
PostgreSQL 中有几种常见的锁类型,以下是几种主要的锁:
- 行级锁(Row-Level Lock): 行级锁只锁定某一行数据,允许其他事务对表中的其他行进行操作。行级锁通常用于更新或删除操作。 常用锁类型:
- FOR UPDATE:锁定被查询到的行,防止其他事务修改或删除这些行。
- FOR NO KEY UPDATE:类似于
FOR UPDATE
,但是允许其他事务对锁定的行插入新行。 - FOR SHARE:允许其他事务读取这些行,但不允许修改。
- FOR KEY SHARE:类似于
FOR SHARE
,但允许在锁定行上插入新行。
- 表级锁(Table-Level Lock): 表级锁锁定整个表,防止其他事务对表中的任何数据进行操作。这种锁通常用于更广泛的操作,例如添加或删除表。 常用锁类型:
- ACCESS SHARE:最轻的锁类型,仅用于查询操作。允许其他事务执行查询。
- ROW EXCLUSIVE:在修改表时使用,阻止其他事务执行对该表的
INSERT
、UPDATE
或DELETE
操作。 - SHARE:用于在进行读取时锁定表,并且防止其他事务修改该表。
- EXCLUSIVE:表级独占锁,其他事务不能修改表。
- ACCESS EXCLUSIVE:最强的锁类型,完全锁定整个表,防止其他事务进行任何操作。
- 元数据锁(Metadata Lock): 用于锁定数据库模式的元数据,防止在修改表结构(例如
ALTER TABLE
)时,其他事务访问表结构。
📝 LOCK 命令的基本语法
使用 LOCK
命令可以显式地锁定一个表或其他数据库对象。
语法:
LOCK TABLE table_name IN lock_mode MODE;
table_name
:要锁定的表名。lock_mode
:要使用的锁类型,可以是多种锁模式之一,如ACCESS SHARE
、ROW EXCLUSIVE
等。
示例:
LOCK TABLE employees IN EXCLUSIVE MODE;
此命令会对 employees
表应用 EXCLUSIVE 锁,防止其他事务修改或访问该表。
📝 锁的使用示例
示例 1:行级锁
假设有两个事务分别执行以下操作:
事务 1:
BEGIN;
SELECT * FROM employees WHERE employee_id = 1 FOR UPDATE;
事务 2:
BEGIN;
SELECT * FROM employees WHERE employee_id = 1 FOR UPDATE;
- 在事务 1 中,
FOR UPDATE
会锁定查询到的行,并防止其他事务修改它。 - 如果事务 2 试图在事务 1 提交之前获取相同的行,它将会被阻塞,直到事务 1 提交或回滚。
示例 2:表级锁
如果需要锁定整个表,可以使用以下命令:
LOCK TABLE employees IN EXCLUSIVE MODE;
此命令会对 employees
表加锁,防止其他事务修改表的内容。
🛑 死锁和避免死锁
死锁(Deadlock) 是指两个或更多的事务相互等待对方持有的资源,从而导致无法继续执行下去的情况。例如,事务 1 持有表 A 的锁,并等待事务 2 释放表 B 的锁,而事务 2 持有表 B 的锁,并等待事务 1 释放表 A 的锁。
死锁的避免:
- 保持事务简短:避免长时间持有锁,确保事务尽可能快地完成。
- 一致的锁顺序:确保所有事务都以相同的顺序获取锁,以减少死锁的风险。
- 适当使用锁的粒度:避免过度使用表级锁,使用行级锁可以减少锁竞争的可能性。
PostgreSQL 内部有一个死锁检测机制,会在发现死锁时自动中断一个事务,并返回死锁错误。
📘 参考资料
- PostgreSQL 官方文档:Locks
- 更多 PostgreSQL 技巧整理自:www.52kanjuqing.com
发表回复