码迷,mamicode.com
首页 > 数据库 > 详细

PostgreSQL并发控制(显式锁定)

时间:2015-08-31 13:44:08      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:



三、显式锁定

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

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

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

表级锁:

  下面是可用的锁模式和它们被PostgreSQL自动使用的场合。你也可以用LOCK命令明确获取这些锁。请注意所有这些锁模式都是表级锁,即使它们的名字包含"row"单词(这些名称是历史遗产)。从某种角度而言,这些名字反应了每种锁模式的典型用法—但是语意却都是一样的。两种锁模式之间真正的区别是它们有着不同的冲突锁集合(参见Table 13-2)。 两个事务在同一时刻不能在同一个表上持有相互冲突的锁。不过,一个事务决不会和自身冲突。比如,它可以在一个表上请求ACCESS EXCLUSIVE然后接着请求 ACCESS SHARE。非冲突锁模式可以被许多事务同时持有。请特别注意有些锁模式是自冲突的(比如,在任意时刻ACCESS EXCLUSIVE模式就不能够被多个事务拥有),但其它锁模式都不是自冲突的(比如,ACCESS SHARE可以被多个事务持有)。

  8大表级锁模式:

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:

与所有模式冲突(8大模式,也包括自己)。这个模式保证其所有者(事务)是可以访问该表的唯一事务。

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

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

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

冲突锁模式对比表

Requested Lock Mode Current Lock Mode






ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE
ACCESS SHARE               X
ROW SHARE             X X
ROW EXCLUSIVE         X X X X
SHARE UPDATE EXCLUSIVE       X X X X X
SHARE     X X   X X X
SHARE ROW EXCLUSIVE     X X X X X X
EXCLUSIVE   X X X X X X X
ACCESS EXCLUSIVE X X X X X X X X

备注: 上图是Postgresql 表级锁的各种冲突模式对照表,‘X’表示冲突项。

行级锁:

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

  行级锁语法(中文文档: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可以是下列之一:

UPDATE
NO KEY UPDATE
SHARE
KEY 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 难以实现的锁定策略。 比如,咨询锁一般用于模拟常见于"平面文件"数据管理系统的悲观锁策略。 虽然可以用存储在表中的一个特定标志达到同样的目的,但是使用咨询锁更快,还可以避免表臃肿, 更可以在会话结束的时候由系统自动执行清理工作。 


四、阻塞与死锁的区别

    参考:http://blog.163.com/caisq_eva/blog/static/12748817120104751552974/

    数据库阻塞的现象: 第一个连接占有资源没有释放,而第二个连接需要获取这个资源。如果第一个连接没有提交或者回滚,第二个连接会一直等待下去,直到第一个连接释放该资源为止。对于阻塞,数据库无法处理,所以对数据库操作要及时地提交或者回滚。

 数据库死锁的现象:第一个连接占有资源没有释放,准备获取第二个连接所占用的资源,而第二个连接占有资源没有释放,准备获取第一个连接所占用的资源。这种互相占有对方需要获取的资源的现象叫做死锁。对于死锁,数据库处理方法:牺牲一个连接,保证另外一个连接成功执行。





 


PostgreSQL并发控制(显式锁定)

标签:

原文地址:http://my.oschina.net/liuyuanyuangogo/blog/499460

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!