PostgreSQL的并发控制

9.3中文文档:http://58.58.27.50:8079/doc/html/9.3.1_zh/mvcc.html

参考博客:中文:http://www.zlovezl.cn/articles/postgresql-concurrency-with-mvcc/

英文:https://devcenter.heroku.com/articles/postgresql-concurrency

本文描述PostgreSQL数据库系统在多个会话试图同时访问同一数据时的表现。并发控制的目标是为所有会话提供高效的访问,同时还要维护严格的数据完整性。每个数据库应用开发人员都应该熟悉本话题。

关于PostgreSQL并发控制的介绍

PostgreSQL为开发者提供了丰富的对数据并发访问进行管理的工具。 在内部,PostgreSQL利用多版本并发控制(MVCC)来维护数据的一致性。这就意味着当检索数据时,每个事务看到的都只是一小段时间之前的数据快照(一个数据库版本),而不是数据的当前状态。这样,如果对每个数据库会话进行事务隔离,就可以避免一个事务看到其它并发事务的更新而导致不一致的数据。MVCC通过避开传统数据库系统锁定的方法,最大限度地减少锁竞争以允许合理的多用户环境中的性能。

使用多版本并发控制比锁定模型的主要优点是在MVCC里,对检索(读)数据的锁请求与写数据的锁请求不冲突,所以读不会阻塞写,而写也从不阻塞读。甚至当通过创新的序列化快照隔离(SSI)级别提供事务隔离的严格等级时,PostgreSQL维持这样的保证。

在PostgreSQL里也有表和行级别的锁定机制,用于给那些无法轻松接受MVCC行为的应用。 不过,恰当地使用MVCC总会提供比锁更好的性能。另外,由应用定义的咨询锁提供了一个获得不依赖于单独事务的锁的机制。

一、事务隔离

SQL标准定义了四个级别的事务隔离。最严格的是串行化,它是通过标准来定义的,也就是说, 保证一组可序列化事务的并发执行以产生同样顺序依次运行它们的同一效果。 其他三个层次是通过现象术语被定义,导致并发事务之间的相互作用,这不应该发生在每个级别中。

各个级别不希望发生的现象是:

  脏读:一个事务读取了另一个未提交事务写入的数据。

  不可重复读:一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交事务修改。

  幻读:一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行因为其它最近提交的事务而发生了改变。

这四种隔离级别和对应的行为在表Table 13-1里描述。

Table 13-1. 标准SQL事务隔离级别

隔离级别  脏读     不可重复读   幻读

读未提交  可能     可能      可能

读已提交  不可能     可能      可能

可重复读  不可能   不可能      可能

可串行化  不可能    不可能      不可能

在PostgreSQL里,你可以请求四种可能的事务隔离级别中的任意一种。但是在内部, 实际上只有三种独立的隔离级别,分别对应读已提交,可重复读和可串行化如果你选择了读未提交的级别, 实际上你用的是读已提交,在重复读的PostgreSQL执行时,幻读是不可能的, 所以实际的隔离级别可能比你选择的更严格。这是 SQL 标准允许的:四种隔离级别只定义了哪种现像不能发生, 但是没有定义那种现像一定发生。PostgreSQL只提供两种隔离级别的原因是, 这是把标准的隔离级别与多版本并发控制架构映射相关的唯一合理方法。可用的隔离级别的行为在下面小节里描述。

要设置一个事务的隔离级别,使用SET TRANSACTION命令。

   特别注意: 一些PostgreSQL数据类型和函数关于事务行为有特定的规则。 尤其是,序列变化(因此列数通过serial声明)对于所有其他的事务是立即可见的, 如果事务改变终止,则不进行回退。参见Section 9.16Section 8.1.4


事务的开启和结束命令:http://58.58.27.50:8079/doc/html/9.3.1_zh/sql-set-transaction.html

begin; --开启事务,可以在此指定事务隔离级别。......

end;/commit;  --- 结束并提交事务rollback;--结束并回滚事务

事务隔离级别详解

读已提交隔离级别( BEGIN TRANSACTION ISOLATION LEVEl READ COMMITTED; )

是PostgreSQL里的缺省隔离级别。

当一个事务运行在这个隔离级别时: SELECT查询(没有FOR UPDATE/SHARE子句)只能看到查询开始之前已提交的数据而无法看到未提交的数据或者在查询执行期间其它事务已提交的数据 (仅读当时数据库快照)。不过,SELECT看得见其自身所在事务中前面更新执行结果。即使它们尚未提交。(注意:在同一个事务里两个相邻的SELECT命令可能看到不同的快照,因为其它事务会在第一个SELECT执行期间提交。)

(对于insert、update,delete操作: 如果表有主键或者唯一约束,那么一旦其他事物执行了未提交的insert,当前事物中的insert将会等待其他提交之后再提交;否则。可以直接执行。)

可重复读隔离级别(BEGIN TRANSACTION ISOLATION LEVEl REPEATABLE READ; )

这个级别和读已提交级别是不一样的。重复读事务中的查询看到的是事务开始时的快照, 而不是该事务内部当前查询开始时的快照,这样, 同一个事务内部后面的SELECT命令总是看到同样的数据等,它们没有看到通过 自身事务开始之后提及的其他事务做出的改变。

使用这个级别的应用必须准备好重试事务,因为串行化失败。

可串行化隔离级别:(BEGIN TRANSACTION ISOLATION LEVEl SERIALIZABLE; )

可串行化级别提供最严格的事务隔离。这个级别为所有已提交事务模拟串行的事务执行, 就好像事务将被一个接着一个那样串行(而不是并行)的执行。不过,正如可重复读隔离级别一样, 使用这个级别的应用必须准备在串行化失败的时候重新启动事务。 事实上,该隔离级别和可重复读希望的完全一样, 它只是监视这些条件,以所有事务的可能的序列不一致的(一次一个)的方式执行并行的可序列化事务执行的行为。 这种监测不引入任何阻止可重复读出现的行为,但有一些开销的监测,检测条件这可能会导致序列化异常 将触发序列化失败

   特别注意:序列化事务隔离级别尚未被添加到热备复制目标中 (正如在Section 25.5中描述的)。 严格的隔离级别目前热备方式上支持可重复读。 当在主库上执行所有永久数据库写入可序列化事务中将确保所有的措施将最终达成一致, 运行在备库上的可重复读事务会看到一个过渡状态,与主库上的任何串行执行的可序列化事务不一致。

二、显式锁定

PostgreSQL提供了多种锁模式用于控制对表中数据的并发访问。 这些模式可以用于在MVCC无法给出期望行为的场合。同样, 大多数PostgreSQL命令自动施加恰当的锁以保证被引用的表在命令的执行过程中不会以一种不兼容的方式被删除或者修改。 比如,在存在其它并发操作的时候,TRUNCATE是不能在同一个表上面执行的

要检查数据库服务器里所有当前正在被持有的锁, 可以使用pg_locks系统视图。 有关监控锁管理器子系统状态的更多信息,请参考章Chapter 27

下面的列表显示了可用的锁模式和它们被PostgreSQL自动使用的场合。 你也可以用LOCK命令明确获取这些锁。两个事务在同一时刻不能在同一个表上持有相互冲突的锁。不过,一个事务决不会和自身冲突。比如,它可以在一个表上请求ACCESS EXCLUSIVE然后接着请求 ACCESS SHARE。 非冲突锁模式可以被许多事务同时持有。请特别注意有些锁模式是自冲突的(比如,在任意时刻ACCESS EXCLUSIVE模式就不能够被多个事务拥有), 但其它锁模式都不是自冲突的(比如,ACCESS SHARE可以被多个事务持有)。

表级锁:

    ACCESS SHARE:

只与ACCESS EXCLUSIVE冲突。

SELECT命令在被引用的表上请求一个这种锁。通常, 任何只读取表而不修改它的命令都请求这种锁模式。

    ROW SHARE:

与EXCLUSIVE和ACCESS EXCLUSIVE锁模式冲突。

SELECT FOR UPDATE和SELECT FOR SHARE命令在目标表上需要一个这样模式的锁 (加上在所有被引用但没有ACCESS SHARE的表上的FOR UPDATE/FOR SHARE锁)。

    ROW EXCLUSIVE:

与SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE锁模式冲突。

UPDATE,DELETE和INSERT命令自动请求这个锁模式(加上所有其它被引用的表上的ACCESS SHARE锁)。 通常,这种锁将被任何修改表中数据的查询请求。

    SHARE UPDATE EXCLUSIVE:

与SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE锁模式冲突。 这个模式保护一个表不被并发模式改变和VACUUM。

VACUUM(不带FULL选项), ANALYZE, CREATE INDEX CONCURRENTLY和ALTER TABLE请求这样的锁。

    SHARE:

与ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE锁模式冲突。 这个模式避免表的并发数据修改。

CREATE INDEX(不带CONCURRENTLY选项)语句要求这样的锁模式。

    SHARE ROW EXCLUSIVE:

与ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE锁模式冲突。这个模式避免表的并发数据修改。 并且是自我排斥的,因此每次只有一个会话可以拥有它。

任何PostgreSQL命令都不会自动请求这个锁模式。

    EXCLUSIVE:

与 ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE锁模式冲突。这个模式只允许并发ACCESS SHARE锁,也就是说, 只有对表的读动作可以和持有这个锁模式的事务并发执行。

任何PostgreSQL命令都不会在用户表上自动请求这个锁模式。

    ACCESS EXCLUSIVE:

与所有模式冲突(ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE和 ACCESS EXCLUSIVE)。这个模式保证其所有者(事务)是可以访问该表的唯一事务。

ALTER TABLE, DROP TABLE, TRUNCATE, REINDEX, CLUSTER和VACUUM FULL命令要求这样的锁。 在LOCK TABLE命令没有明确声明需要的锁模式时,它是缺省锁模式。

Tip: 只有ACCESS EXCLUSIVE阻塞SELECT (不包含FOR UPDATE/SHARE语句)。

一旦请求已获得某种锁,那么该锁模式将持续到事务结束。但是如果在建立保存点之后才获得锁, 那么在回滚到这个保存点的时候将立即释放所有该保存点之后获得的锁。这与ROLLBACK取消所有保存点之后对表的影响的原则一致。 同样的原则也适用于PL/pgSQL异常块中获得的锁: 一个跳出块的错误将释放在块中获得的锁。

行级锁:

行级锁可以是排他的或者是共享的。特定行上的排他行级锁是在行被更新的时候自动请求的。 该锁一直保持到事务提交或者回滚。行级锁不影响对数据的查询,它们只阻塞对同一行的写入

行级锁语法:http://58.58.27.50:8079/doc/html/9.3.1_zh/sql-select.html

FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE 和 FOR KEY SHARE是锁定子句;他们影响 SELECT如何从表中锁定行作为获得的行。锁定子句的一般形式:

FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT ]

这里的lock_strength可以是下列之一:

UPDATENO KEY UPDATESHAREKEY SHARE

FOR UPDATE令那些被SELECT检索出来的行被锁住, 就像要更新一样。这样就避免它们在当前事务结束前被其它事务修改或者删除;也就是说, 其它企图UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR NO KEY UPDATE, SELECT FOR SHARE 或 SELECT FOR KEY SHARE这些行的事务将被阻塞,直到当前事务结束。同样, 如果一个来自其它事务的UPDATE, DELETE, SELECT FOR UPDATE已经锁住了某个或某些选定的行,SELECT FOR UPDATE 将等到那些事务结束,并且将随后锁住并返回更新的行(或者不返回行,如果行已经被删除)。 但是,在REPEATABLE READ或SERIALIZABLE事务内部, 如果在事务开始时要被锁定的行已经改变了,那么将抛出一个错误。更多的讨论参阅Chapter 13

FOR NO KEY UPDATE的行为类似,只是获得的锁比较弱:这个锁将不锁定尝试在相同的行上获得锁的SELECT FOR KEY SHARE命令。这个锁模式也可以通过任何不争取FOR UPDATE锁的UPDATE获得。

FOR SHARE的行为类似,只是它在每个检索出来的行上要求一个共享锁,而不是一个排它锁。一个共享锁阻塞其它事务在这些行上执行UPDATE, DELETE, SELECT FOR UPDATE 或 SELECT FOR NO KEY UPDATE,却不阻止他们执行SELECT FOR SHARE 或 SELECT FOR KEY SHARE。

FOR KEY SHARE的行为类似于FOR SHARE,只是锁比较弱: 阻塞SELECT FOR UPDATE但不阻塞SELECT FOR NO KEY UPDATE。一个共享键块阻塞其他事务执行DELETE或任意改变键值的UPDATE, 但是不阻塞其他UPDATE,也不阻止SELECT FOR NO KEY UPDATE, SELECT FOR SHARE, 或 SELECT FOR KEY SHARE。

死锁:

显式锁定的使用可能会增加死锁的可能性,死锁是指两个(或多个)事务相互持有对方期待的锁。

咨询锁:

PostgreSQL允许创建由应用定义其含义的锁。这种锁被称为咨询锁, 因为系统并不强迫其使用— 而是由应用来保证其被恰当的使用。 咨询锁可用于 MVCC 难以实现的锁定策略。 比如,咨询锁一般用于模拟常见于"平面文件"数据管理系统的悲观锁策略。 虽然可以用存储在表中的一个特定标志达到同样的目的,但是使用咨询锁更快,还可以避免表臃肿, 更可以在会话结束的时候由系统自动执行清理工作。

时间: 2024-08-24 08:18:49

PostgreSQL的并发控制的相关文章

PostgreSQL并发控制(显式锁定)

三.显式锁定 PostgreSQL提供了多种锁模式用于控制对表中数据的并发访问.这些模式可以用于在MVCC无法给出期望行为的场合.同样,大多数PostgreSQL命令自动施加恰当的锁以保证被引用的表在命令的执行过程中不会以一种不兼容的方式被删除或者修改. 比如,在存在其它并发操作的时候,TRUNCATE是不能在同一个表上面执行的. 要检查数据库服务器里所有当前正在被持有的锁,可以使用pg_locks系统视图.有关监控锁管理器子系统状态的更多信息,请参考章Chapter 27. 下面的列表显示了可

PostgreSQL数据库内核分析 笔记(这本书没有怎么很好的看,主要就是一些数据结构、概念和流程的文字介绍)

PostgreSQL数据库内核分析 跳转至: 导航. 搜索 目录 1系统概述 2体系结构 3存储管理 4索引 5查询编译 6查询执行 7事务处理与并发控制 8数据库安全 9附录A 用Eclipse开发和调试 系统概述 初始化数据库:./initdb --no-locale -D ../data ./pg_ctl start -D ../data 数据库命令:initdb createuser dropuser createdb dropdb pg_dump pg_restore pg_ctl v

PostgreSQL 系统的基本体系结构

PostgreSQL 使用客户机/服务器(C/S)的模式提供服务,一个PostgreSQL会话由下列相关的进程(程序)组成: (1)一个服务器端进程.该进程管理数据库文件,接受客户端与数据库的连接,且代表客户端对数据库进行操作.该进程的程序名叫做 postgres. (2)前端应用,即需要进行数据库操作的客户端应用.客户端应用可能本身就是多种多样的:它们可以是一个字符界  面的工具, 也可以是一个图形界面的应用,或者是一个通过访问数据库来显示网页的 web 服务器,或者是一个特殊的数据库管理工具

postgresql数据库和mysql数据库的对比分析

1.Posgresql是进程模式,多进程,单线程,类似的还有Oracle.而MYSQL采用的是线程模式,单进程,多线程,对此,大家在运行数据库的时候可以查看任务管理器,SQL Server也是如此. 众所周知,多进程,进程模式,利用CPU时间片轮转,可以利用更充分CPU,因此光拿多核单台机器上来说,他明显在支持高并发性能方面更胜一筹.而线程模式呢,开一个线程显然要比开一个进程所耗费的资源要少,另外在不同线程之间的环境转换和访问公用的存储区域,显然比在不同进程之间要快,所以它的处理速度要快,对资源

[转]PostgreSQL事务处理机制

原文链接:http://blog.chinaunix.net/uid-20726500-id-4040024.html 事务的实现原理可以解读为DBMS采取何种技术确保事务的ACID特性.PostgreSQL针对ACID的实现技术如下表所示. 表1:事务的4个特征ACID及响应的实现技术 ACID 实现技术 原子性 MVCC 一致性 约束(主键,外键等) 隔离性 MVCC 持久性 WAL 可以看到PostgreSQL中支撑ACID的主要是MVCC和WAL两项技术.MVCC和WAL是两个比较成熟的

何为PostgreSQL?

PostgreSQL 是以加州大学伯克利分校计算机系开发的 POSTGRES, Version 4.2 为基础的对象关系型数据库管理系统(ORDBMS).POSTGRES 领先的许多概念只是在非常迟的时候才出现在商业数据库中. PostgreSQL 是最初伯克利代码的一个开放源码的继承人.它支持大部分 SQL 标准并且提供了许多其它现代特性: 复杂查询 外键 触发器 视图 事务完整性 多版本并发控制 另外,PostgreSQL 可以用许多方法进行扩展,比如通过增加新的: 数据类型 函数 操作符

SQL事务的四种隔离级别和MySQL多版本并发控制

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的那些改变时可见的,那些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. ReadUncommitted(读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结构.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取未提交的数据,也被称之为脏读(Dirty Read) ReadCommitted(读取提交内容) 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的).它

多版本并发控制(MVCC)在分布式系统中的应用

问题 最近项目中遇到了一个分布式系统的并发控制问题.该问题可以抽象为:某分布式系统由一个数据中心D和若干业务处理中心L1,L2 ... Ln组成:D本质上是一个key-value存储,它对外提供基于HTTP协议的CRUD操作接口.L的业务逻辑可以抽象为下面3个步骤: read: 根据keySet {k1, ... kn}从D获取keyValueSet {k1:v1, ... kn:vn} do: 根据keyValueSet进行业务处理,得到需要更新的数据集keyValueSet' {k1':v1

浅谈PostgreSQL数据库

近期工作重点一直放在数据库设计方面,借助这次机会抽时间整理了一些我对PostgreSQL数据库的理解,同时也是对近段时间学习的一个总结.对于很多人而言或许没有听说过这个数据库,通常我们耳边伴随的都是Oracle.MySQL.Microsoft SQL Server一类的关系型数据库. 但看下数据库排行榜,或许更能直观的认识到PostgreSQL数据库的强大与普遍 既然PostgreSQL排行这么高,那为何在国内名气不如其他数据库呢?这其中我认为重点在于两点:一.市场推广力度的问题:二.应用场景与