PostgreSQL中什么是事务

77次阅读
没有评论

共计 2865 个字符,预计需要花费 8 分钟才能阅读完成。

这篇文章主要介绍 PostgreSQL 中什么是事务,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

一、什么是事务?

事务可以看作是一个操作的有序集,这些操作应作为整体来对待,即集内所有的操作都成功的时候,该事务才被认为是成功的,否则的话,即使其中只有一个操作失败,该事务也会被认为是不成功。如果所有的操作全部成功,那么事务就会被提交,这时它的所作的修改才能被所有其他数据库进程所用。如果操作失败,该事务就会被回滚,同时事务内部所有已完成操作所做的修改会被全部撤销。在事务提交之前,一次事务期间所作的修改,只对拥有此事务的进程可用。之所以这样做,是为了防止其他线程使用了事务修改的数据后,事务随后又发生了回滚,从而导致数据完整性错误。
 

事务功能是企业数据库的关键所在,因为许多业务流程是由多步组成的,下面我们以在线购物为例进行说明。在结帐时,顾客的购物车会跟现有库存进行比对,以确保有现货。接下来,顾客必须提供收费与交货信息,这时就需要检查相应的信用卡是否可用,并从中扣款。然后,需要从产品库存清单中扣除相应的数量,如果库存不足,还应向采购部门发出通知。在这些步骤中,只要有一步发生错误,那么所有修改都不应该生效。假设没有现货的情况下,还是从顾客的信用卡中扣了款的话,那么顾客会很生气,问题就会很严重了。同样地,作为在线商家,当信用卡无效的时候,您也肯定不希望从存货清单中扣除此次顾客选择的商品数量,或者因此而发出相应的采购通知。

我们这里所说的事务,必须满足四大要件:

l 原子性:事务所有的步骤必须全部成功; 否则,任何步骤都不会被提交。

l 一致性:事务所有的步骤必须全部成功; 否则,所有的数据都会恢复到事务开始之前的状态。

l 隔离性:在事务完成之前,所有已执行的步骤必须与系统保持隔离。

l 持久性:所有提交的数据,系统必须加以恰当保存,并保证万一系统发生故障时仍能将数据恢复到有效状态。

PostgreSQL 的事务支持功能完全遵循上述四项基本原则 (有时候人们简称为 ACID),从而能够有效保证数据库的完整性。

二、PostgreSQL 的事务隔离

PostgreSQL 的事务支持是通过通常所说的多版本并发控制或者 MVCC 方法实现的,也就是说,每当事务进行处理时,它看到的是自己的数据库快照,而非底层数据的实际状态。这使得任何给定的事务无法看到其它已经启动但是尚未提交的事务对数据所作的部分修改。这项原则就是所谓的事务隔离。

SQL 标准规定了三种属性以用来确定一个事务处于四级隔离级别的哪一级,这些属性如下所示:

l 脏读:一个事务读取了另一个未提交的并行事务写的数据

l 不可重复读:当一个事务重新读取前面读取过的数据时,发现该数据已经被另一个已提交的事务修改过

l 幻读:一个事务重新执行一个查询时,返回一套符合查询条件的行,发现这些行因为其他最近提交的事务而发生了改变

这三种情况确定了一个事务的隔离级别,所有四种水平如表 1 所示。

表 1 SQL 标准事务隔离级别

#FormatImgID_0#

PostgreSQL 允许您请求四种可能的事务隔离级别中的任意一种。但是在内部,实际上只有两种可用的隔离级别,分别对应读已提交和可串行化。如果你选择了读未提交的级别,实际上你用的是读已提交,在你选择可重复的读级别的时候,实际上你用的是可串行化,所以实际的隔离级别可能比你选择的更严格。虽然这看起来是有悖于我们的直觉,但是 SQL 标准的确允许这样做,因为四种隔离级别只定义了哪种现象不能发生,但是没有定义那种现象一定发生,所以除了不允许的事务特性之外,所有的特性都是允许的。举例来说,如果您请求可重复读模式,那么该标准只是要求您不准脏读以及不可重读,但是却没有要求允许幻读。因此,可串行化事务模式满足可重复读模式的要求,即使它跟定义没有完全吻合。因此,您应当确切的知道,当您请求读未提交模式的时候,您实际得到的却是读已提交模式; 而当您请求可重复读的时候,实际得到的是可串行化模式。您还应当意识到,默认情况下,如果您没有请求一个特定的隔离级别,那么您得到的将是读已提交隔离级别。

下面我们了解一下读已提交和可串行化之间的主要区别。在读已提交模式下 SELECT 查询只能看到该查询开始之前提交的数据而永远无法看到未提交的数据或者是在查询执行时其他并行的事务提交的改变; 不过 SELECT 的确看得见同一次事务中前面更新的结果,即使它们还没提交也看得到。实际上,一个 SELECT 查询看到一个在该查询开始运行的瞬间该数据库的一个快照。请注意两个相邻的 SELECT 命令可能看到不同的数据,哪怕它们是在同一个事务里,因为其它事务会在第一个 SELECT 执行的时候提交。当一个事务处于可串行化级别的时候,一个 SELECT 查询只能看到在该事务开始之前提交的数据而永远看不到未提交的数据或事务执行中其他并行事务提交的修改; 不过,SELECT 的确看得到同一次事务中前面的更新的效果,即使事务还没有提交也一样。这个行为和读已提交级别是不太一样,它的 SELECT 看到的是该事务开始时的快照,而不是该事务内部当前查询开始时的快照。这样,一个事务内部后面的 SELECT 命令总是看到同样的数据。这意味着,读已提交模式下一个事务内部后面的 SELECT 命令可以看到不同的数据,但是在可串行化模式下却总是看到同样的数据。

对于以上区别,请读者一定弄清楚。虽然刚看上去有些复杂,但是只要抓住两个要点,理解起来还是很容易的:首先,PostgreSQL 运行事务的并发运行,也就是说一个事务执行的时候,并不妨碍另一事务对相同数据操作。其次,一定注意快照的概念,事务提交前操作的是数据快照而非数据库本身,同时注意不同隔离级别使用的是何时的快照 mdash; mdash; 事务开始之前的快照,还是事务内部操作开始之前的快照? 我想只要抓住了以上要点,我们就能很好的把握各种隔离级别之间的区别了。

上面介绍了事务的基本概念,接下来我们开始演示如何在 PostgreSQL 客户端中使用事务。

三、创建示例表

下面,我们通过一个具体的在线交易应用为例来阐述上面介绍的事务概念。为此,我们需要先给这个示例程序在名为 company 的数据库中创建两个表:participant 和 trunk。同时,我们还会介绍各个表的用途和结构。建好表后,我们还需为它们填入一些样本数据,具体如下所示。

我们首先创建 Participant 表,这个表用来存放参与物品交换者的信息,包括他们的姓名、电子邮件地址和可用现金:

1 CREATE TABLE participant (
2 participantid SERIAL,
3 name TEXT NOT NULL,
4 email TEXT NOT NULL,
5 cash NUMERIC(5,2) NOT NULL,
6 PRIMARY KEY (participantid)
7 );
8 CREATE TABLE span

以上是“PostgreSQL 中什么是事务”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-19发表,共计2865字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)