- /* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
- #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 */
一, 表级锁
大多数的表级锁是由内置的 SQL 命令获得的, 但他们也可以通过锁命令来明确获取. 可使用的表级锁包括:
访问共享(ACCESS SHARE)
SELECT 命令可在查询中引用的表上获得该锁. 一般规则是所有的查询中只有读表才获取此锁.
行共享(ROW SHARE)
SELECT FOR UPDATE 和 SELECT FOR SHARE 命令可在目标表上获得该锁(以及查询中所有引用的表的访问共享锁).
行独占(ROW EXCLUSIVE)
UPDATE,INSERT 和 DELETE 命令在目标表上获得该锁(以及查询中所有引用的表的访问共享锁). 一般规则是所有修改表的查询获得该锁.
共享更新独占(SHARE UPDATE EXCLUSIVE)
VACUUM(不含 FULL),ANALYZE,CREATE INDEX CONCURRENTLY, 和一些 ALTER TABLE 的命令获得该锁.
共享(SHARE)
CREATE INDEX 命令在查询中引用的表上获得该锁.
共享行独占(SHARE ROW EXCLUSIVE)
不被任何命令隐式获取.
排他(EXCLUSIVE)
这个锁模式在事务获得此锁时只允许读取操作并行. 它不能由任何命令隐式获取.
访问独占(ACCESS EXCLUSIVE)
ALTER TABLE,DROP TABLE,TRUNCATE,REINDEX,CLUSTER 和 VACUUM FULL 命令在查询中引用的表上获得该锁. 此锁模式是 LOCK 命令的默认模式.
重要的是要知道, 所有这些锁都是表级锁, 即使它们名称里有行 (ROW) 字.
每个锁模式的最重要的信息是与彼此冲突的模式列表. 在同一时间同一个表中, 2 个事务不能同时保持相冲突的锁模式. 事务永远不会与自身发生冲突. 非冲突的锁可以支持多事务并发. 同样重要的是要知道有的模式和自身冲突. 一些锁模式在获得后会持续到事务结束. 但如果锁是在建立一个保存点后获得, 保存点回滚后锁会被立刻释放.
二, 行级锁
在 Postgres 9.1 和 9.2 有两种行级锁模式, 但在 Postgres 9.3 和 9.4 有四种行级锁模式.
Postgres 不会记住修改的行在内存中的任何信息, 所以一次锁定的行的数目没有限制. 然而, 锁定一行可能会导致磁盘写入, 例如, SELECT FOR UPDATE 修改选定的行并标记它们锁定, 所以会导致磁盘写入.
Postgres 9.1 和 9.2 中的行级锁
在这两种版本中, 只有 2 种行级锁: 排他或共享锁.
当行更新或删除时, 会自动获得排他行级锁.
行级锁不阻止数据查询, 它们只阻止同一行写入.
排他行级锁可由 SELECT FOR UPDATE 命令明确获得, 即使行没有实际更改.
共享行级锁可由 SELECT FOR SHARE 命令获得. 一个共享锁并不阻止其他事务获取同样的共享锁. 然而, 当任何其他事务持有共享锁时, 事务的更新, 删除或排他锁都不被允许.
更新(FOR UPDATE)
这种模式导致 SELECT 读取的行的更新被锁定. 这可以防止它们被其他事务锁定, 修改或删除. 即尝试 UPDATE,DELETE,SELECT FOR UPDATE,SELECT FOR NO KEY UPDATE,SELECT FOR SHARE 或 SELECT FOR KEY SHARE 的其他事务将被阻塞. 删除一行, 更新一些列也可以获得到此种锁模式(目前的列集是指那些具有唯一索引, 并且可被用作外键 - 但将来这可能会改变).
无键更新(FOR NO KEY UPDATE)
这种模式与 FOR UPDATE 相似, 但是更弱 - 它不会阻塞 SELECT FOR KEY SHARE 锁模式. 它通过不获取更新锁的 UPDATE 命令获得.
共享(FOR SHARE)
这种模式与无键更新锁类似, 除了它可以获取共享锁(非排他). 一个共享锁阻止其他事务在这些行上进行 UPDATE,DELETE,SELECT FOR UPDATE 或 SELECT FOR NO KEY UPDATE 操作, 但并不阻止它们进行 SELECT FOR SHARE 或 SELECT FOR KEY SHARE.
键共享(FOR KEY SHARE)
行为类似于共享, 但该锁是较弱的: 阻止了 SELECT FOR UPDATE, 但不阻止 SELECT FOR NO KEY UPDATE. 一个键共享锁阻止其他事务进行 DELETE 或任何更改该键值的 UPDATE, 但不妨碍任何其他 UPDATE,SELECT FOR NO KEY UPDATE,SELECT FOR SHARE 或者 SELECT FOR KEY SHARE.
select * from test for update;
这个锁会让查询到的数据不会被更新, 删除, 或者被其他事务锁定, 但是可以查询;
lock table test;
在一个事务中执行, 会让别的事务无法使用该表;
pg 是默认读已提交, 即使是前面未提交的事务, 在本事务中途提交, 也能读取已经提交的数据.- 在同一个事务, 两次读取, 允许获取不一样的数据. 即不可重复读.
可重复读的隔离级别更高, 最后是串行化.
插入更新删除获取的是表的 row exclusive 锁, 允许查询. 创建索引会获取的是 share 锁, 不允许插入数据.
来源: http://www.bubuko.com/infodetail-3829407.html