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

    做自己的太阳,成为别人的光!
  • 相关阅读:
    Flask莫名其妙特别慢
    MySQL老是提示视图没有主键
    Mysql写入中文出错
    Sqlite向MySql导入数据
    大智慧专业财务PFFIN(N,M)函数N的取值一览表
    js的技巧
    拍拍贷年化收益率的推算
    Sqlite的多表连接更新
    Kali Linux 64位架构安装Veil-Evasion
    修改Kali Linux 2020.1主题颜色
  • 原文地址:https://www.cnblogs.com/botaoli/p/15307158.html
Copyright © 2020-2023  润新知