成都网站建设
|
域名注册
|
虚拟主机
|
网站制作
|
网站案例
|
网站优化
|
网站推广
|
企业邮局
|
服务器租用
|
广告设计
首页
服务器租用
企业邮箱
虚拟主机
网站程序
营销推广
网站建设
域名注册
前端开发
网站备案
网站空间
|
独立ip空间
|
双线主机
|
php虚拟主机
|
免备案空间
|
香港空间
|
云空间
|
vps主机
|
服务器租用
|
服务器托管
|
云服务器
|
jsp空间
|
网站空间报价
虚拟主机
主机管理
主机购买
数据库
主机续费升级
FTP上传
服务器租用
web服务器
FTP服务器
服务器托管
服务器租用
vps主机服务器
企业邮箱
企业邮箱优势
企业邮箱设置
邮箱收发问题
邮箱功能讲解
邮箱其他问题
网站程序
java教程
asp程序
asp.net程序
vb编程
php程序
营销推广
seo优化
网站推广
搜索引擎
免费资源
网站建设
网站方案
网站改版
网页设计
网站维护
网站策划
域名注册
域名转入\转出
英文域名
通用网址
中文域名
域名解析
前端开发
html
jQuery
JavaScript教程
css
div+css
网站备案
备案流程指南
备案资料下载
备案常见问题
各省备案要求
移动互联网
wap手机网站
app应用开发
微网站
当前位置:
创新互联
>>
常见问题
>>
虚拟主机
>>
数据库
>>
PostgreSQL客户端处理事务功能详解
PostgreSQL客户端处理事务功能详解
作者:创新互联 文章来源:数据库 点击数:
更新时间:2012-04-17
PostgreSQL所针对的目标,与目前使用MySQL
数据库
的人群很接近。那么究竟PostgreSQL有何优势?本文将为大家做出解释。本文将介绍PostgreSQL的事务处理功能的基本概念,并讲解如何通过PostgreSQL客户端以及从PHP脚本内部来执行各种事务。通过本文,您将学习什么是事务,PostgreSQL是如何实现它们的,以及怎样在自己的PHP应用程序中如何使用事务。一、什么是事务? 事务可以看作是一个数据库操作的有序集,这些操作应作为整体来对待,即集内所有的操作都成功的时候,该事务才被认为是成功的,否则的话,即使其中只有一个操作失败,该事务也会被认为是不成功。如果所有的操作全部成功,那么事务就会被提交,这时它的所作的修改才能被所有其他数据库进程所用。如果操作失败,该事务就会被回滚,同时事务内部所有已完成操作所做的修改会被全部撤销。在事务提交之前,一次事务期间所作的修改,只对拥有此事务的进程可用。之所以这样做,是为了防止其他线程使用了事务修改的数据后,事务随后又发生了回滚,从而导致数据完整性错误。事务功能是企业数据库的关键所在,因为许多业务流程是由多步组成的,下面我们以在线购物为例进行说明。在结帐时,顾客的购物车会跟现有库存进行比对,以确保有现货。接下来,顾客必须提供收费与交货信息,这时就需要检查相应的信用卡是否可用,并从中扣款。然后,需要从产品库存清单中扣除相应的数量,如果库存不足,还应向采购部门发出通知。在这些步骤中,只要有一步发生错误,那么所有修改都不应该生效。假设没有现货的情况下,还是从顾客的信用卡中扣了款的话,那么顾客会很生气,问题就会很严重了。同样地,作为在线商家,当信用卡无效的时候,您也肯定不希望从存货清单中扣除此次顾客选择的商品数量,或者因此而发出相应的采购通知。我们这里所说的事务,必须满足四大要件:原子性:事务所有的步骤必须全部成功;否则,任何步骤都不会被提交。一致性:事务所有的步骤必须全部成功;否则,所有的数据都会恢复到事务开始之前的状态。隔离性:在事务完成之前,所有已执行的步骤必须与系统保持隔离。持久性:所有提交的数据,系统必须加以恰当保存,并保证万一系统发生故障时仍能将数据恢复到有效状态。 PostgreSQL的事务支持功能完全遵循上述四项基本原则(有时候人们简称为ACID),从而能够有效保证数据库的完整性。二、PostgreSQL的事务隔离 PostgreSQL的事务支持是通过通常所说的多版本并发控制或者MVCC方法实现的,也就是说,每当事务进行处理时,它看到的是自己的数据库快照,而非底层数据的实际状态。 这使得任何给定的事务无法看到其它已经启动但是尚未提交的事务对数据所作的部分修改。这项原则就是所谓的事务隔离。 SQL标准规定了三种属性以用来确定一个事务处于四级隔离级别的哪一级,这些属性如下所示:脏读:一个事务读取了另一个未提交的并行事务写的数据不可重复读:当一个事务重新读取前面读取过的数据时,发现该数据已经被另一个已提交的事务修改过幻读:一个事务重新执行一个查询时,返回一套符合查询条件的行,发现这些行因为其他最近提交的事务而发生了改变这三种情况确定了一个事务的隔离级别,所有四种水平如表1所示。表1 SQL标准事务隔离级别 PostgreSQL允许您请求四种可能的事务隔离级别中的任意一种。但是在内部,实际上只有两种可用的隔离级别,分别对应读已提交和可串行化。如果你选择了读未提交的级别,实际上你用的是读已提交,在你选择可重复的读级别的时候,实际上你用的是可串行化,所以实际的隔离级别可能比你选择的更严格。虽然这看起来是有悖于我们的直觉,但是SQL标准的确允许这样做,因为四种隔离级别只定义了哪种现象不能发生,但是没有定义那种现象一定发生,所以除了不允许的事务特性之外,所有的特性都是允许的。举例来说,如果您请求可重复读模式,那么该标准只是要求您不准脏读以及不可重读,但是却没有要求允许幻读。因此,可串行化事务模式满足可重复读模式的要求,即使它跟定义没有完全吻合。因此,您应当确切的知道,当您请求读未提交模式的时候,您实际得到的却是读已提交模式;而当您请求可重复读的时候,实际得到的是可串行化模式。您还应当意识到,默认情况下,如果您没有请求一个特定的隔离级别,那么您得到的将是读已提交隔离级别。下面我们了解一下读已提交和可串行化之间的主要区别。在读已提交模式下SELECT 查询只能看到该查询开始之前提交的数据而永远无法看到未提交的数据或者是在查询执行时其他并行的事务提交的改变;不过 SELECT 的确看得见同一次事务中前面更新的结果,即使它们还没提交也看得到。实际上,一个 SELECT 查询看到一个在该查询开始运行的瞬间该数据库的一个快照。请注意两个相邻的 SELECT 命令可能看到不同的数据,哪怕它们是在同一个事务里,因为其它事务会在第一个SELECT执行的时候提交。当一个事务处于可串行化级别的时候,一个 SELECT 查询只能看到在该事务开始之前提交的数据而永远看不到未提交的数据或事务执行中其他并行事务提交的修改;不过,SELECT 的确看得到同一次事务中前面的更新的效果,即使事务还没有提交也一样。这个行为和读已提交级别是不太一样,它的 SELECT 看到的是该事务开始时的快照,而不是该事务内部当前查询开始时的快照。这样,一个事务内部后面的SELECT命令总是看到同样的数据。这意味着,读已提交模式下一个事务内部后面的SELECT命令可以看到不同的数据,但是在可串行化模式下却总是看到同样的数据。对于以上区别,请读者一定弄清楚。虽然刚看上去有些复杂,但是只要抓住两个要点,理解起来还是很容易的:首先,PostgreSQL运行事务的并发运行,也就是说一个事务执行的时候,并不妨碍另一事务对相同数据操作。其次,一定注意快照的概念,事务提交前操作的是数据快照而非数据库本身,同时注意不同隔离级别使用的是何时的快照——事务开始之前的快照,还是事务内部操作开始之前的快照?我想只要抓住了以上要点,我们就能很好的把握各种隔离级别之间的区别了。上面介绍了事务的基本概念,接下来我们开始演示如何在PostgreSQL客户端中使用事务。三、创建示例表下面,我们通过一个具体的在线交易应用为例来阐述上面介绍的事务概念。为此,我们需要先给这个示例程序在名为company的数据库中创建两个表:participant和trunk。同时,我们还会介绍各个表的用途和结构。建好表后,我们还需为它们填入一些样本数据,具体如下所示。我们首先创建Participant表,这个表用来存放参与物品交换者的信息,包括他们的姓名、电子邮件地址和可用现金: CREATE TABLE participant ( participantid SERIAL, name TEXT NOT NULL, email TEXT NOT NULL, cash NUMERIC(5,2) NOT NULL, PRIMARY KEY (participantid) ); CREATE TABLE participant ( participantid SERIAL, name TEXT NOT NULL, email TEXT NOT NULL, cash NUMERIC(5,2) NOT NULL, PRIMARY KEY (participantid) ); 然后,我们开始创建trunk 表。这个表存储参与者所有的物品的有关信息,包括属主、名称、描述和价格: CREATE TABLE trunk ( trunkid SERIAL, participantid INTEGER NOT NULL REFERENCES participant(participantid), name TEXT NOT NULL, price NUMERIC(5,2) NOT NULL, description TEXT NOT NULL, PRIMARY KEY (trunkid) ); 用到的表都建好了,下面我们开始添加样本数据。为简单起见,我们这里只添加了两名参与者,即Tom和Jack;并为trunks表添加了少量的物品,如下所示: INSERT INTO participant (name,email,cash) VALUES ('Tom','Tom@example.com','1100.00'); INSERT INTO participant (name,email,cash) VALUES ('Jack','Jack@example.com','1150.00'); INSERT INTO trunk (participantid,name,price,description) VALUES (1,'Linux CD','1.00','Complete OS on a CD'); INSERT INTO trunk (participantid, name,price,description) VALUES (2,'ComputerABC','12.99','a book about computer!'); INSERT INTO trunk (participantid,name,price,description) VALUES (2,'Magazines','6.00','Stack of Computer Magazines'); 四、简单的示例应用为了让读者切身体会事务的运行机制,我们从命令行来运行我们的示例程序。我们的示例程序将演示两个交易者如何通过现金的形式来互换物品。在考察代码之前,先让我们看一下更容易理解的伪代码: 1. 参加者Tom请求一个物品,例如位于参加者Jack的虚拟储物箱中的ComputerABC。 2. 参加者Tom向参加者Jack的帐户上划过去$12.99的现金。结果是,Tom的帐户中现金数量减去12.99,而Jack的帐户的现金数量则增加12.99。 3. 将ComputerABC的属主改为参加者Tom。如您所见,这个过程中的每一步对于该交易的整体成功来说都是非常关键的,所以必须保证我们的数据不会由于单步失败而遭到破坏。当然,现实中的情景要比这里复杂得多,例如必须检查购买方是否具有足够的现金等等,不过为了简单起见,我们忽略了一些细节,以便读者将主要精力都放到事务这一主题上来。我们可以提交START TRANSACTION命令来启动事务处理: company=# START TRANSACTION; START TRANSACTION 注意,START TRANSACTION还有一个别名,即BEGIN命令,虽然两者都能完成该任务,但是我们还是推荐您使用后者,因为它符合SQL规范。接下来,从Tom的帐户中扣除$12.99: company=# UPDATE participant SET cash=cash-12.99 WHERE participantid=1; UPDATE 1 然后,为Jack的帐户增加$12.99: company=# UPDATE participant SET cash=cash+12.99 WHERE participantid=2; UPDATE 1 然后,将ComputerABC过户给Tom: company=# UPDATE trunk SET participantid =1 WHERE name='ComputerABC' AND company-# participantid=2; UPDATE 1 现在,我们已经完成了一笔交易,接下来我们开始介绍PostgreSQL的另一个特性:savepoint。注意,Savepoint功能是从PostgreSQL 8.
PostgreSQL对决InnoDB 多版本并发控制大比拼
:上一篇
ASP链接数据库
:下一篇
数据库相关文章
PostgreSQL对决Inno...
NTILE函数在SQL Serv...
Oracle跨平台迁移结构而不迁...
从Web查询数据库之PHP与My...
MSSQL使用说明
MYSQL使用帮助
MSSQL和MYSQL有什么区别...
如何限制Mssql数据库占用最大...
创新互联专注虚拟主机/网站空间多年,高速、稳定、安全有保障!虚拟主机首选创新互联。
移动互联网
|
网站备案
|
前端开发
|
域名注册
|
网站建设
|
营销推广
|
网站程序
|
虚拟主机
|
企业邮箱
|
服务器租用
|
热门搜索
服务电话:028-86922220 13518219792 公司地址:成都市太升南路288号锦天国际A幢10楼2号
企业邮箱:
service@cdxwcx.com
版权所有:成都创新互联科技有限公司 蜀ICP备09010846号
成都网站建设
数据库 PostgreSQL处理事务功能