http://www.wohedb.com  中文数据库管理系统9.3.2 行级锁
    除了表级锁以外,还有行级锁。行级锁的模式有互斥和共享两种。当一个数据行被删除或更新时,事务会自动得到这个数据行上的互斥行级锁。一个事务获得的行级锁只有在事务提交或回滚以后才会被释放。行级锁不会影响查询操作,如果有其它事务企图更新同一个数据行,该事务将会进入等待状态,直到持有行级锁的事务被回滚或提交。如果一个命令只是想锁住数据行,而不是想更新数据行,可以使用SELECT FOR UPDATE,同一个事务以后发出的命令就可以随意地修改被锁住的数据行。      如果想得到一个数据行上的共享锁,使用命令SELECT FOR SHARE。多个不同的事务可以在同一个数据行上同时持有共享锁。如果一个事务已经在一个数据行上持有共享锁,那么其它的事务就不能更新和删除这个数据行,也不能在这个数据行上得到互斥锁。     PostgreSQL不会限制一个事务一次能同时锁住的数据行的最大数目,但每锁住一个数据行就会有一次写磁盘的操作。     除了表级锁和行级锁,数据库中还存在数据页级别的共享和互斥锁,数据页级别的锁用来协调对表的的某个数据页并发访问操作,它是由数据库自动得到和释放的。开发应用程序时不必关心数据页级别的锁,只要知道它存在就可以了。 9.3.3 死锁
    使用锁来协调多个事务对表中的数据的并发访问,很容易产生死锁,即两个或多个事务中的每个事务都拥有其它的某个或多个事务需要的锁资源,所有的事务都会无限期地等待下去。     系统会自动检测数据库中是否有死锁发生,如果有,会回滚一个造成死锁的事务,让其它的因死锁而等待的事务继续执行。 9.3.4 建议锁(Advisory Locks)
    PostgreSQL提供了一种被称为建议锁的锁机制。建议锁的含义是有应用程序自己特定的,何时得到和释放建议锁也是由应用程序自己控制的,数据库只是提供得到和释放建议锁的接口供用户使用。建议锁同事务没有任何关系,在一个事务中得到的建议锁,即使在事务被回滚以后仍然存在。建议锁的所有者是会话而非事务,一个会话可以多次得到同一个建议锁(如果一个会话执行了n次得到同一个建议锁的操作,那么它必须执行n次释放这个建议锁的操作,否则该建议锁不会被真正地释放,仍然被这个会话所有)。在一个会话结束后,该会话持有的所有建议锁都会被自动释放。     可以查看视图pg_locks得到当前会话持有的所有建议锁的列表。建议锁存放在数据库的共享内存中,数据库中的建议锁的最大数目受参数max_locks_per_transaction 和max_connections控制。     数据库提供的用于处理建议锁的函数参见第7.22节表7-50。    下面是一些使用建议锁的实例: SELECT pg_advisory_lock(id) FROM foo WHERE id = 12345; -- ok SELECT pg_advisory_lock(q.id) FROM(  SELECT id FROM foo WHERE id > 12345 LIMIT 100;) q; 9.4 在应用程序级别检查数据的一致性
    因为PostgreSQL中的只读查询无论在任何隔离事务级别下都不会在读取的数据上加锁,一个事务读取的数据可能已被其它并发执行的事务修改。每个事务都会看到一个数据库内容的快照,并发执行的事务可能看到不同的数据库快照。如果事务想保证自己读取的数据在自己提交或回滚以前不被其它的事务修改,应该使用SELECT FOR UPDATE或SELECT FOR SHARE来读取数据(而不是只使用SELECT),也可以使用LOCK TABLE来锁住表,不让其它事务更新表中的数据。     如果应用程序希望一个事务在执行的过程中所引用的表的数据不能有任何变化,可以先用LOCK TABLE命令锁住所有的表,然后再执行其它的命令。     一般使用显示的加锁命令时,事务应该运行在Read Committed隔离级别下,也可以使用Serializable隔离级别。在Serializable隔离级别下使用LOCK TABLE命令时,注意LOCK TABLE命令应该作为事务发出的第一条命令。 9.5 锁与索引
    PostgresSQL在访问索引时也会使用锁来控制对索引的并发访问,不同类型的索引的加锁模式如下: B-tree 和GiST 索引 使用短期的共享或互斥数据页级别的锁来控制对索引的并发访问。在每个索引数据行被读取或删除以后,锁会被立即释放。不会出现死锁的情况。 哈希索引 使用共享或互斥数据页级别的锁来控制对索引的并发访问。在每个哈希桶被处理以后,锁会被立即释放。可能会出现死锁。 GIN 索引 使用短期的共享和互斥数据页级别的锁来控制对索引的并发访问。在每个索引数据行被读取或删除以后,锁会被立即释放 。GIN类型索引的插入操作可能素要比较大的工作量。     对标量数据类型建立索引时,应该使用B-tree索引。对非标量类型的数据建立索引,应该使用Gist或GIN索引。