9.2. 事务隔离
SQL 标准 用三个必须在并行的事务之间避免的现象定义了四个级别的事务隔离。 这些不希望发生的现象是:
脏读(dirty reads)
一个事务读取了另一个未提交的并行事务写的数据。
不可重复读(non-repeatable reads)
一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过。
幻读(phantom read)
一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最近提交的事务而发生了改变。
这四种隔离级别和对应的行为在Table 9-1 里描述.
Table 9-1. SQL 隔离级别
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
PostgreSQL 提供读已提交(read committed)和可串行化(serializable)隔离级别。
9.2.1. 读已提交隔离级别
读已提交(Read Committed) 是 PostgreSQL 里的缺省隔离级别。 当一个事务运行在这个隔离级别时, 一个 SELECT 查询只能看到查询开始之前提交的数据而永远 无法看到未提交的数据或者是在查询执行时其他并行的事务提交做的改变。 (不过 SELECT 的确看得见同一次事务中前面更新 的结果.即使它们还没提交也看得到.) 实际上,一个 SELECT 查询看到一个在该查询开始 运行的瞬间该数据库地一个快照。 请注意两个相邻的 SELECT 可能看到不同 的数据,哪怕它们是在同一个事务里,因为其它事务会在第一个 SELECT执行的时候提交.
UPDATE, DELETE, 或者 SELECT FOR UPDATE 在搜索目标行的时候的行为和 SELECT 一样:它们只能找到在查询开始的时候已经提交 的行。 不过,这样的目标行在被找到的时候可能已经被其它并发的事务更新(或者删除,或者标记为更新的)。 在这种情况下,即将进行的更新将等待第一个更新事务提交或者回滚(如果它还在处理)。 如果第一个更新回滚,那么它的作用将被忽略,而第二个更新者将继续更新最初发现的行。 如果第一个更新者提交,那么如果第一个更新者删除了该行,则第二个更新者将忽略该行, 否则它将视图在该行的已更新的版本上施加它的操作。系统将重新计算查询搜索条件 (WHERE 子句),看看该行已更新的办不那是否仍然符合搜索条件。如果是, 则第二个更新继续其操作,从该行的已更新版本开始。
因为上面的规则,正在更新的规则可能会看到不一致的快找 --- 它们可以看到 影响它们试图更新的并发更新查询的效果,但是它们看不到那些查询对数据库 里其它行的作用。这样的行为令读已提交模式不适合用于哪种涉及复杂搜索条件 的查询。不过,它对于简单的情况而言是正确的。比如,假设我们用类似下面这样 的查询更新银行余额:






