在连接锁之前需要了解两个概念,session 和 transaction:
session: 客户端连接到PG服务器,就开始一个session,在一个session中可以执行任意多个transaction transaction: 一段sql(一个或多个), begin/begin transaction/start transaction开始一个transaction, commit/rollback结束。 在一个transaction中,所有的sql要么全部成功,要么全部失败(原子性)
锁的分类
- 表级锁
- 行级锁
- 页级锁
- 劝告锁
表级锁
执行语句时自动获得,或者在事务中显示地使用lock语句
- access share(访问共享锁)
SELECT 命令在被引用的表上会获得一个这种模式的锁。通常,任何只读取表而不修改它的查询都将获取这种表模式。
- row share(行共享)
防止其他事务修改正在被当前事务读取的数据,从而确保当前事务读取数据的一致性。但是,它并不阻止其他事务读取这些数据,所以称为“行共享”锁。(select for share/select for update)
- row exclusive(行独占)
ROW EXCLUSIVE锁是一种防止其他事务同时修改同一行数据的锁,但其他事务仍然可以查询(读取)这一行。当一个事务通过
UPDATE
,DELETE
或INSERT
命令在一行上获取ROW EXCLUSIVE
锁时,其他事务不能对其进行更新,直到ROW EXCLUSIVE
锁被释放。总的来说,
ROW SHARE
和ROW EXCLUSIVE
锁都允许其他事务读取被锁定的行,但ROW EXCLUSIVE
锁会阻止其他事务修改被锁定的行,而ROW SHARE
锁则不会。 - share update exclusive(共享更新独占)
SHARE UPDATE EXCLUSIVE
锁是一种中等级别的锁模式。当一个事务在表上获取SHARE UPDATE EXCLUSIVE
锁时,其他事务不能获得SHARE UPDATE EXCLUSIVE
,SHARE
,SHARE ROW EXCLUSIVE
,EXCLUSIVE
或ACCESS EXCLUSIVE
锁。这意味着,一旦一个事务在表上获得了
SHARE UPDATE EXCLUSIVE
锁,其他事务就不能更改该表的定义(例如,添加或删除列)或删除该表。然而,即使一个表上有SHARE UPDATE EXCLUSIVE
锁,其他事务仍然可以在该表上插入、更新和删除行,也可以获取ROW SHARE
或ROW EXCLUSIVE
锁。SHARE UPDATE EXCLUSIVE
锁通常用于那些需要在不阻止并发读写的情况下,保护表免受结构改变的影响。例如,SHARE UPDATE EXCLUSIVE
锁可以用于在创建一个新的索引或添加一个外键约束时,防止其他事务同时删除表或更改表的定义。 - share(共享)
SHARE
锁是一种更严格的锁模式。如果一个事务在表上获得了SHARE
锁,其他事务就不能再获得该表的SHARE UPDATE EXCLUSIVE
,SHARE
,SHARE ROW EXCLUSIVE
,EXCLUSIVE
或ACCESS EXCLUSIVE
锁。这意味着,一旦一个事务在表上获得了
SHARE
锁,其他事务就不能更改该表的定义(例如,添加或删除列)或删除该表。然而,即使一个表上有SHARE
锁,其他事务仍然可以在该表上插入、更新和删除行,也可以获取ROW SHARE
或ROW EXCLUSIVE
锁。SHARE
锁通常用于在不阻止并发数据改变的情况下,保护表免受结构改变的影响。例如,SHARE
锁可以用于在创建一个新的索引或添加一个外键约束时,防止其他事务同时删除表或更改表的定义。 - share row exclusive(共享行独占)
SHARE ROW EXCLUSIVE
是PostgreSQL中的一种锁模式。当一个事务在表上获取SHARE ROW EXCLUSIVE
锁时,其他事务不能获取该表的SHARE
、SHARE ROW EXCLUSIVE
、EXCLUSIVE
或ACCESS EXCLUSIVE
锁,也不能在该表上获取ROW SHARE
、ROW EXCLUSIVE
或SELECT FOR UPDATE/SHARE
锁。这意味着,当一个事务在表上获取
SHARE ROW EXCLUSIVE
锁时,其他事务不能改变该表的结构,也不能在该表上插入、更新或删除行,直到SHARE ROW EXCLUSIVE
锁被释放。SHARE ROW EXCLUSIVE
锁主要用于那些需要保护表免受并发读写和结构改变的操作,如VACUUM FULL
。这种锁模式能确保在当前事务执行的同时,其他事务不能对表进行任何读写操作或结构改变。 - exclusive(独占)
EXCLUSIVE
锁是 PostgreSQL 中的一种锁模式。当一个事务在表上获取EXCLUSIVE
锁时,其他事务不能获取该表的SHARE
、SHARE ROW EXCLUSIVE
、EXCLUSIVE
或ACCESS EXCLUSIVE
锁,也不能在该表上获取ROW SHARE
、ROW EXCLUSIVE
或SELECT FOR UPDATE/SHARE
锁。这意味着,当一个事务在表上获取
EXCLUSIVE
锁时,其他事务不能改变该表的结构,也不能在该表上插入、更新或删除行,直到EXCLUSIVE
锁被释放。EXCLUSIVE
锁主要用于那些需要保护表免受并发读写和结构改变的操作。这种锁模式能确保在当前事务执行的同时,其他事务不能对表进行任何读写操作或结构改变。 - access exclusive(访问独占)
ACCESS EXCLUSIVE
是最严格的锁模式。当一个事务在表上获取ACCESS EXCLUSIVE
锁时,其他事务不能获取该表的任何其他类型的锁。这意味着,当一个事务在表上获取
ACCESS EXCLUSIVE
锁时,其他事务不能读取或更改该表的数据,也不能更改该表的结构,直到ACCESS EXCLUSIVE
锁被释放。ACCESS EXCLUSIVE
锁通常用于那些需要对表进行大规模改变的操作,如ALTER TABLE
、DROP TABLE
、TRUNCATE
、REINDEX
、CLUSTER
、VACUUM FULL
等。这种锁模式能确保在当前事务执行的同时,其他事务不能对表进行任何操作。
行级锁
同一个事务可能会在相同的行上保持冲突的锁,甚至是在不同的子事务中。但是除此之外,两个事务永远不可能在相同的行上持有冲突的锁。
行级锁不影响数据查询,它们只阻塞对同一行的写入者和加锁者。行级锁在事务结束时或保存点回滚的时候释放,就像表级锁一样
- for update
- for no key update
使用
SELECT FOR UPDATE
语句时,被选中的行将被锁定,直到当前事务结束。这意味着,如果有另一个事务试图UPDATE
、DELETE
、SELECT FOR UPDATE
、SELECT FOR NO KEY UPDATE
、SELECT FOR SHARE
或SELECT FOR KEY SHARE
被锁定的行,那么这个事务将被阻塞,直到当前事务结束。例如,假设有两个并发事务,事务 A 和事务 B。事务 A 先执行
SELECT FOR UPDATE
语句,锁定了一些行。然后,事务 B 试图UPDATE
这些被锁定的行。在这种情况下,事务 B 将被阻塞,直到事务 A 结束并释放了这些行的锁。FOR NO KEY UPDATE
在 PostgreSQL 中的作用类似于FOR UPDATE
,都是用来锁定被选定的行直到当前事务结束。不过它们之间有一个主要的区别。当你使用
FOR UPDATE
锁定一行时,其他事务不能更新该行,也不能更新任何与该行有外键关系的行。这是因为FOR UPDATE
会锁定该行的所有键(主键和外键)。而当你使用
FOR NO KEY UPDATE
锁定一行时,其他事务不能更新该行,但是可以更新与该行有外键关系的行。这是因为FOR NO KEY UPDATE
只锁定该行的主键,不锁定外键。所以,如果你需要锁定一行,但是不希望阻止其他事务更新与该行有外键关系的行,你可以使用
FOR NO KEY UPDATE
。BEGIN; SELECT * FROM orders WHERE id = 1 FOR UPDATE; -- 这里可以进行一些更新操作,例如: UPDATE orders SET status = 'processed' WHERE id = 1; COMMIT; BEGIN; SELECT * FROM orders WHERE id = 1 FOR NO KEY UPDATE; -- 这里可以进行一些更新操作,例如: UPDATE orders SET status = 'processed' WHERE id = 1; COMMIT;
- for share
- for key share
页级锁
劝告锁
可重入