加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

超详细的PG事务隔离级别总结,值得收藏

发布时间:2019-08-06 04:06:08 所属栏目:MySql教程 来源:波波说运维
导读:今天主要介绍一下PG的事务隔离,事务隔离和锁机制是息息相关的,希望大家这两块都可以掌握。下面先看下SQL标准的四种隔离级别。 四种隔离级别 SQL标准定义了四种隔离级别。最严格的是可序列化,在标准中用了一整段来定义它,其中说到一组可序列化事务的任
副标题[/!--empirenews.page--]

今天主要介绍一下PG的事务隔离,事务隔离和锁机制是息息相关的,希望大家这两块都可以掌握。下面先看下SQL标准的四种隔离级别。

超详细的PG事务隔离级别总结,值得收藏

四种隔离级别

SQL标准定义了四种隔离级别。最严格的是可序列化,在标准中用了一整段来定义它,其中说到一组可序列化事务的任意并发执行被保证效果和以某种顺序一个一个执行这些事务一样。其他三种级别使用并发事务之间交互产生的现象来定义,每一个级别中都要求必须不出现一种现象。注意由于可序列化的定义,在该级别上这些现象都不可能发生。

在各个级别上被禁止出现的现象是:

  • 脏读:一个事务读取了另一个并行未提交事务写入的数据。
  • 不可重复读:一个事务重新读取之前读取过的数据,发现该数据已经被另一个事务(在初始读之后提交)修改。
  • 幻读:一个事务重新执行一个返回符合一个搜索条件的行集合的查询, 发现满足条件的行集合因为另一个最近提交的事务而发生了改变。
  • 序列化异常:成功提交一组事务的结果与一次运行这些事务的所有可能顺序不一致。

SQL标准和PostgreSQL实现的事务隔离级别如下:

超详细的PG事务隔离级别总结,值得收藏

事务隔离级别

在PostgreSQL中可以请求四种标准事务隔离级别中的任意一种。 但是在内部,只实现了三种不同的隔离级别,即:PostgreSQL的读未提交模式的行为类似于读已提交。 这是因为这是把标准的隔离级别映射到PostgreSQL的多版本并发控制架构的唯一合理方法。

要设置一个事务的事务隔离级别,使用SET TRANSACTION命令

  1. SET TRANSACTION transaction_mode [, ...] 
  2. SET TRANSACTION SNAPSHOT snapshot_id 
  3. SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...] 
  4. where transaction_mode is one of: 
  5.  ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } 
  6.  READ WRITE | READ ONLY 
  7.  [ NOT ] DEFERRABLE 

超详细的PG事务隔离级别总结,值得收藏

1. 读已提交隔离级别

读已提交是PostgreSQL中的默认隔离级别。

当一个事务运行使用这个隔离级别时, 一个查询(没有FOR UPDATE/SHARE子句)只能看到查询开始之前已经被提交的数据, 而无法看到未提交的数据或在查询执行期间其它事务提交的数据。(假设SQL查询了10s,这10s中间插入的新数据是看不到的)实际上,SELECT查询看到的是一个在查询开始运行的瞬间该数据库的一个快照。不过SELECT可以看见在它自身事务中之前执行的更新的效果,即使它们还没有被提交。还要注意的是,即使在同一个事务里两个相邻的SELECT命令可能看到不同的数据, 因为其它事务可能会在第一个SELECT开始和第二个SELECT开始之间提交。

UPDATE、DELETE、SELECT FOR UPDATE和SELECT FOR SHARE命令在搜索目标行时的行为和SELECT一样: 它们将只找到在命令开始时已经被提交的行。

带有ON CONFLICT DO UPDATE子句的INSERT的行为类似。 在读已提交模式下,建议插入的每一行都将插入或更新。除非有无关的错误, 否则这两个结果中的一个是有保证的。如果冲突源于另一个其影响对于 INSERT不可见的事务,则将对该行使用UPDATE子句, 即使可能没有命令常规可见的该行的版本。

带有ON CONFLICT DO NOTHING子句的INSERT 可能由于其影响对INSERT快照不可见的另一事务的结果而不插入行。 同样,只有在读已提交模式下才是这种情况。

因为上面的规则,正在更新的命令可能会看到一个不一致的快照: 它们可以看到并发更新命令在它尝试更新的相同行上的作用, 但是却看不到那些命令对数据库里其它行的作用。 这样的行为令读已提交模式不适合用于涉及复杂搜索条件的命令。不过, 它对于更简单的情况是正确的。例如,考虑用这样的命令更新银行余额:

  1. BEGIN; 
  2. UPDATE accounts SET balancebalance = balance + 100.00 WHERE acctnum = 12345; 
  3. UPDATE accounts SET balancebalance = balance - 100.00 WHERE acctnum = 7534; 
  4. COMMIT; 

如果两个这样的事务同时尝试修改帐号 12345 的余额,那我们很明显希望第二个事务从账户行的已更新版本上开始工作。(这里是考虑第二个update的时候accounts表数据改动了)因为每个命令只影响一个已经决定了的行,让它看到行的已更新版本不会导致任何麻烦的不一致性。

因为在读已提交模式中,每个命令都是从一个新的快照开始的,而这个快照包含在该时刻已提交的事务, 因此同一事务中的后续命令将看到任何已提交的并行事务的效果。以上的焦点在于单个命令是否看到数据库的绝对一致的视图。

读已提交模式提供的部分事务隔离对于许多应用而言是足够的,并且这个模式速度快并且使用简单。 不过,它不是对于所有情况都够用。做复杂查询和更新的应用可能需要比读已提交模式提供的更严格一致的数据库视图。

2. 可重复读隔离级别

可重复读隔离级别只看到在事务开始之前被提交的数据;它从来看不到未提交的数据或者并行事务在本事务执行期间提交的修改(不过,查询能够看见在它的事务中之前执行的更新,即使它们还没有被提交)。这是比SQL标准对此隔离级别所要求的更强的保证,标准只描述了每种隔离级别必须提供的最小保护。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读