PostgreSQL7.0手册-用户手册-13. 多版本并行控制
--------------------------------------------------------------------------------
第十三章. 多版本并行控制
内容
介绍
事务隔离
读已提交隔离级别
可串行化隔离级别
锁和表
锁和索引
应用层的数据完整性检查
多版本并行控制(Multi-Version Concurrency Control (MVCC))是用于提高数据库在一个多用户环境下性能的高级技术。Vadim Mikheev 为 Postgres 提供了MVCC的实现。
介绍
与其他使用锁来进行并行控制的数据库系统不同,Postgres 利用多版本模型来维护数据的一致性。这就意味着当检索数据库时,每个事务都看到一个数据的一段时间前的快照(一个 数据库版本),而不管正在处理的数据当前的状态。这样,如果对每个数据库会话进行 事务隔离,就可以避免一个事务看到因为其它并行的事务更新同一行数据而导致的不连贯的数据。
多版本和锁定模型的主要区别是在 MVCC 里,对检索(读)数据的锁要求与写数据的锁要求不冲突,所以读不会阻塞写,而写也从不阻塞读。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
事务隔离
ANSI/ISOSQL 用三个必须在并行的事务之间避免的现象定义了四个级别的事务隔离。这些不希望发生的现象是:
读污染(dirty reads)
一个事务读取了被另一个未提交的并行的事务写的数据。
不可重复的读(non-repeatable reads)
一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。
错误读取(phantom read)
一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行中插入了被其他已提交的事务提交的行。
这四种隔离级别和对应的特性在下面描述。
表 13-1. Postgres 隔离级别
读污染(Dirty Read) 不可重复的读(Non-Repeatable Read) 错误读取(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
Postgres 提供读已提交(read committed)和可串行化(serializable)隔离级别。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
读已提交隔离级别
读已提交(Read Committed)是Postgres 里的缺省隔离级别。当一个事务运行在这个隔离级别时,一个查询只能看到查询开始之前的数据而永远无法看到脏数据或者是在查询执行时其他并行的事务提交做的改变。
如果一个正在执行一个 UPDATE 语句(或者 DELETE 或者 SELECT FOR UPDATE)的查询返回的行正在被另一个并行的未提交的事务更新,那么第二个试图更新此行的事务将等待另一个事务的提交或者回卷。如果发生了回卷,等待中的事务可以继续修改此行。如果发生了提交(并且此行仍然存在;也就是说,没有被另一个事务删除),这个查询将对该行再执行一便以检查新行版本是否满足查询搜索条件。如果新行版本满足查询搜索条件,那么该行将被更新(或删除或被标记为更新)。
注意 SELECT 或 INSERT 语句执行的结果(在一个查询里)将不会被并行事务影响。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
可串行化隔离级别
可串行化(Serializable)提供最高级别的事务隔离。当一个事务处于可串行化级别,一个查询只能看到在事务开始之前提交的数据而永远看不到脏数据或事务执行中其他并行事务提交的修改。所以,这个级别模拟串行事务执行,就好象事务将被一个接着一个那样串行的,而不是并行的执行。
如果一个正在执行一个 UPDATE 语句(或者 DELETE 或者 SELECT FOR UPDATE)的查询返回的行正在被另一个并行的未提交的事务更新,那么第二个试图更新此行的事务将等待另一个事务的提交或者回卷。如果发生了回卷,等待中的事务可以继续修改此行。如果发生一个并行的事务的提交,一个可串行化的事务将回卷,并返回下面信息。
ERROR: Can't serialize access due to concurrent update
因为一个可串行化的事务在可串行化事务开始之后不能更改被其他事务更改过的行。
注意: SELECT 或 INSERT 语句执行的结果(在一个查询里)将不会被并行事务影响。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
锁和表
Postgres 提供多种锁模式来控制对表中数据的并行访问。有些锁模式是在语句执行之前由Postgres 自动施加的,而其他的提供用来由应用使用的。一个事务里要求的所有锁模式(除了 AccessShareLock)都是在整个事务期间保有的。
除了锁以外,短期的共享/排他销也在共享的缓冲池中用于控制对表页面的读/写访问。销在一条记录抓取或者更新后马上被释放。
表级锁
AccessShareLock
一个内部锁模式,进行查询时自动施加在被查询的表上。语句执行完成后,Postgres 释放这些锁。
只与 AccessExclusiveLock 冲突。
RowShareLock
被 SELECT FOR UPDATE 和用于 IN ROW SHARE MODE 的 LOCK TABLE 语句要求。
与 ExclusiveLock 和 AccessExclusiveLock 模式冲突。
RowExclusiveLock
被 UPDATE, DELETE, INSERT 和用于IN ROW EXCLUSIVE MODE 的 LOCK TABLE 语句要求。
与 ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式冲突。
ShareLock
被 CREATE INDEX 和用于IN SHARE MODE 的 LOCK TABLE 语句所要求。
与 RowExclusiveLock,ShareRowEx
第十三章. 多版本并行控制
内容
介绍
事务隔离
读已提交隔离级别
可串行化隔离级别
锁和表
锁和索引
应用层的数据完整性检查
多版本并行控制(Multi-Version Concurrency Control (MVCC))是用于提高数据库在一个多用户环境下性能的高级技术。Vadim Mikheev 为 Postgres 提供了MVCC的实现。
介绍
与其他使用锁来进行并行控制的数据库系统不同,Postgres 利用多版本模型来维护数据的一致性。这就意味着当检索数据库时,每个事务都看到一个数据的一段时间前的快照(一个 数据库版本),而不管正在处理的数据当前的状态。这样,如果对每个数据库会话进行 事务隔离,就可以避免一个事务看到因为其它并行的事务更新同一行数据而导致的不连贯的数据。
多版本和锁定模型的主要区别是在 MVCC 里,对检索(读)数据的锁要求与写数据的锁要求不冲突,所以读不会阻塞写,而写也从不阻塞读。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
事务隔离
ANSI/ISOSQL 用三个必须在并行的事务之间避免的现象定义了四个级别的事务隔离。这些不希望发生的现象是:
读污染(dirty reads)
一个事务读取了被另一个未提交的并行的事务写的数据。
不可重复的读(non-repeatable reads)
一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。
错误读取(phantom read)
一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行中插入了被其他已提交的事务提交的行。
这四种隔离级别和对应的特性在下面描述。
表 13-1. Postgres 隔离级别
读污染(Dirty Read) 不可重复的读(Non-Repeatable Read) 错误读取(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
Postgres 提供读已提交(read committed)和可串行化(serializable)隔离级别。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
读已提交隔离级别
读已提交(Read Committed)是Postgres 里的缺省隔离级别。当一个事务运行在这个隔离级别时,一个查询只能看到查询开始之前的数据而永远无法看到脏数据或者是在查询执行时其他并行的事务提交做的改变。
如果一个正在执行一个 UPDATE 语句(或者 DELETE 或者 SELECT FOR UPDATE)的查询返回的行正在被另一个并行的未提交的事务更新,那么第二个试图更新此行的事务将等待另一个事务的提交或者回卷。如果发生了回卷,等待中的事务可以继续修改此行。如果发生了提交(并且此行仍然存在;也就是说,没有被另一个事务删除),这个查询将对该行再执行一便以检查新行版本是否满足查询搜索条件。如果新行版本满足查询搜索条件,那么该行将被更新(或删除或被标记为更新)。
注意 SELECT 或 INSERT 语句执行的结果(在一个查询里)将不会被并行事务影响。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
可串行化隔离级别
可串行化(Serializable)提供最高级别的事务隔离。当一个事务处于可串行化级别,一个查询只能看到在事务开始之前提交的数据而永远看不到脏数据或事务执行中其他并行事务提交的修改。所以,这个级别模拟串行事务执行,就好象事务将被一个接着一个那样串行的,而不是并行的执行。
如果一个正在执行一个 UPDATE 语句(或者 DELETE 或者 SELECT FOR UPDATE)的查询返回的行正在被另一个并行的未提交的事务更新,那么第二个试图更新此行的事务将等待另一个事务的提交或者回卷。如果发生了回卷,等待中的事务可以继续修改此行。如果发生一个并行的事务的提交,一个可串行化的事务将回卷,并返回下面信息。
ERROR: Can't serialize access due to concurrent update
因为一个可串行化的事务在可串行化事务开始之后不能更改被其他事务更改过的行。
注意: SELECT 或 INSERT 语句执行的结果(在一个查询里)将不会被并行事务影响。
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
锁和表
Postgres 提供多种锁模式来控制对表中数据的并行访问。有些锁模式是在语句执行之前由Postgres 自动施加的,而其他的提供用来由应用使用的。一个事务里要求的所有锁模式(除了 AccessShareLock)都是在整个事务期间保有的。
除了锁以外,短期的共享/排他销也在共享的缓冲池中用于控制对表页面的读/写访问。销在一条记录抓取或者更新后马上被释放。
表级锁
AccessShareLock
一个内部锁模式,进行查询时自动施加在被查询的表上。语句执行完成后,Postgres 释放这些锁。
只与 AccessExclusiveLock 冲突。
RowShareLock
被 SELECT FOR UPDATE 和用于 IN ROW SHARE MODE 的 LOCK TABLE 语句要求。
与 ExclusiveLock 和 AccessExclusiveLock 模式冲突。
RowExclusiveLock
被 UPDATE, DELETE, INSERT 和用于IN ROW EXCLUSIVE MODE 的 LOCK TABLE 语句要求。
与 ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式冲突。
ShareLock
被 CREATE INDEX 和用于IN SHARE MODE 的 LOCK TABLE 语句所要求。
与 RowExclusiveLock,ShareRowEx

