阅读 54

PostgreSQL锁级别及什么操作获取什么锁

PostgreSQL锁级别及什么操作获取什么锁

 

/* 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锁,不允许插入数据。

 

原文:https://www.cnblogs.com/botaoli/p/15307158.html

文章分类
百科问答
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐