postgresql并发控制

postgreSQL提供了很多工具来管理并发访问,数据一致性通过多版本模型来维护。也就是说每个当在查询数据库的时候每个事务看到一个数据的快照,不管潜在数据的当前状态。这避免事务看到不一致的数据,可能导致并发事务更新相同的数据行,为每个数据库会话提供了事务隔离。多版本并发控制通过避免传统数据库的锁机制,最小化了锁竞争,提供了在多用户环境下的合理性能。

mvc模型的并发控制比锁的主要好处是,mvcc锁住查询的数据与写的数据不冲突,读不锁写,写不锁读。即使在使用序列号快照隔离的最严格的事务隔离级别的时候,PostgreSQL也确保是这样的。

事务隔离

标准sql定义了4个事务隔离级别,最严格的是Serializable,该级别保证了任何并发执行的序列化事务以一定顺序执行都会有相同的结果。另外的3种级别定义取决于并发事务交互产生的现象。现象有下面几个:

脏读:事务读取了未提交事务的数据

不可重复读:事务重新读取之前度过的数据,发现该数据已经被别的事务修改了。

幻想读:事务重新执行的查询,返回了结果发现由于别的事务最近的提交导致跟之前查询的结果不一样了。

在PostgreSQL中,你可以请求4个标准事务隔离等级中的任意一个,但是内部的,只有3个唯一的隔离级别,read committed,repeatable read,和serializable.当你选择read uncommitted级别的时候,你实际上是read comitted,在选择repeatable read级别的时候,幻想读是不存在的。所以,实际的隔离级别要比你选择的更加严格些。PostgreSQL提供3种隔离级别的原因是,这是一个明智的方法映射标准隔离级别到多版本并发控制。

读提交隔离级别

该级别在PostgreSQL中是默认的级别,这个是和oracle是一样的。这个级别下,select只能看到在查询开始前已经提交的数据。永远也看不到未提交的和在查询过程中提交的数据。更新删除操作的行为与select都是一样的。然而在找到结果集后,该结果集可能已经被别的事务更新或删除了,这种情况下,可能的更新会等待第一个更新事务来提交或回滚,如果提交回滚了,那么对结果没有影响,第二个更新可以处理原来找到的结果集,如果第一个更新提交了,删除了行,第二个更新将会忽略这些行,否则第二个更新就在更新的行上做操作,命令会重新评估更新的行是否与查询条件相匹配。因为上面的条件,对于一个更新操作看到不一致的快照是可能的。它能看到它要试图更新的行被并发事务更新的影响,但是看不到这些命令在别的行上的影响。这个行为使得读提交模式不适用与包含复杂查询条件。

可重复读隔离级别

可重复读隔离级别只看到在事务开始之前提交了的数据,永远也看不到未提交的数据或在事务执行过程中的提价。然而查询看不到它自己事务内部之前的更新。

序列化事务隔离级别

这个级别对于所有提交的事务仿制序列事务执行。好像所有的事务的执行是一个接着一个。而不是并行。

PostgreSQL提供了不同种类的锁模式来控制访问表中数据的并发。这些模式被应用控制的锁使用提供了mvcc不能提供的行为。

表级别锁

access share

只与access exclusize锁模式冲突,select命令在相关的表上需要这个模式的锁。

row share

与execlusive和access exclusive模式锁冲突,select for update和elect for share命令需要这个模式的锁。

row exclusive

与share,share row exclusive,exclusive和access exclusive模式锁冲突,update,delete,和insert要求这种模式的锁。通常,这种模式的锁被任意的修改数据的命令要求。

share update exclusive

与 share update exclusive,share,share row execlusive,exclusive和access exclusive锁模式冲突,这种模式保护表并发模式修改和vaccum运行,被vacuum,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,shar update exclusive,share,share row exclusive,exclusive,和access exclusive锁模式需要。这种锁模式被任意的PostgreSQL命令需要。

exclusive与row share,row exclusie,share update exclusie,share,share row exclusive,exclusive和access exclusive锁模式冲突。这种锁模式自动被PostgreSQL命令获取。

access exclusive

与所有的锁模式冲突。这种模式确保持有者是唯一的事务访问表的。在使用命令lock table的时候,是这种锁模式。只有access exclusive锁阻塞select命令。

行级锁

除了表级锁,还有行级锁,可以使排他或是共享锁。一个行级排他锁在行被更新的时候自动获取。为了在不修改行的情况下获取一个行级排他锁,使用select for update命令

。一旦行级锁被获取了,事务可以更细行多次而不用担心冲突。

postgreSQL不会记得在内存中修改的任何信息,因此行锁的数量没有限制,然而,锁一行可能引起磁盘写。select for update修改选择的行来标记他们被锁,会导致磁盘写。

除了表和行锁,页级的共享/排他锁被用来控制在共享buffer pool中的读/写表页。这些锁在行被获取或更新后立即释放。应用程序开发者通常不用关心页级锁。

对于死锁postgreSQL也是会自动来检测死锁,并终止一个事务。

建议锁

PostgreSQL提供了一个创建锁的方法,称为建议锁,因为系统不强迫他们使用,依赖应用程序正确的使用他们。Advisory locks can be useful for locking strategies that are an awkward fit for
the MVCC model. For example, a common use of advisory locks is to emulate pessimistic locking
strategies  typical  of  so  called  “flat  file”  data  management  systems.  While  a  flag  stored  in  a  table
could be used for the same purpose, advisory locks are faster, avoid table bloat, and are automatically
cleaned up by the server at the end of the session.

有2中方法来获取建议锁,在会话级别或是在事务级别。一旦在会话级别获取了,建议锁一直被持有直到明确的释放或是会话终结。不像是标准的锁请求,session-level advisory lock requests  do not honor transaction semantics;在一个事务中获取的锁在回滚后仍然会被后面的rollback持有,and likewise an unlock is effectiv even if the caling transaction fails later.一个锁可以被拥有它的进程多次获取。对每一个完整的锁请求,必须有相应的解锁请求在锁被实际释放之前。事务级别的锁请求,更像是普通锁请求。在事务结束的时候自动释放,没有明确的解锁操作。通常比会话级别的行为更加方便。会话级别的和事务级别的锁对相同建议锁的请求会阻塞彼此。

会话拥有的完整的建议锁列表也可以再pg_locks系统视图中查看到。建议锁和常规锁都存放在共享内存池中,共享内存被max_lock_per_transaction和max_connections决定。一定不要耗尽内存,这样就不能分配锁了。这强加了服务器能分配的最多建议锁数量的限制。在一些特定环境下使用建议锁,尤其是在包含明确的排序和limit的语句。

锁和索引

尽管PostgreSQL提供了对表数据的不阻塞read/write,但是对于索引访问还没有提供。下面是索引的处理

B-tree,GiST和SP-GiST索引

短期共享/排他页级锁被用来read/write访问。在每个索引行被获取或插入后,锁马上释放。这些索引类型提供了最高并发。

hash索引

共享/排他 hash-bucket-level锁被用来read/write访问,锁在整个bucket被处理后释放,bucket-leve锁提供比index-level更好的并发,但是锁持有时间长过索引操作会发生死锁。

GIN索引

短期共享/排他 页级锁被用来read/write访问,在每个索引行被获取或插入后锁马上释放,但是注意GIN-indexed值的插入通常对每行有很多索引键插入。因此GIN用于单值的插入。

B-tree索引提供最好的并发性能,因为他们有比hash索引更多的特色,所以对需要索引标量数据的并发应用推荐这种索引类型,当处理非标量数据时,B-tree没有用,GiST,SP-GiST或GIN索引应该被使用。



命令总结:

查看数据库中的锁

select * from pg_locks;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值