事务是所有数据库系统的一个基本概念。 一次事务的要点就是它把多个步骤捆绑成了一个单一的,不成功则成仁的操作。 其它并发的事务是看不到在这些步骤之间的中间状态的,并且如果发生了一些问题, 导致该事务无法完成,那么所有这些步骤都完全不会影响数据库。
比如,假设一个银行的数据库包含各种客户帐户的余额,以及每个分行的总余额。 假设我们要记录一次从 Alice 的帐户到 Bob 的帐户的金额为 $100.00 的支付动作。那么,完成这个任务的简单到极点的 SQL 命令象下面这样
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
UPDATE branches SET balance = balance - 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Alice');
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Bob';
UPDATE branches SET balance = balance + 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Bob');
这些命令的细节在这儿并不重要;重要的是这里牵涉到了好几个独立的更新来完成这个相当简单的操作。 我们的银行官员会希望要么所有这些更新都生效,要么全部不起作用。 我们当然不希望一次系统崩溃就导致 Bob 收到 100 块不是 Alice 支付的钱, 也不希望 Alice 老是不花钱从 Bob 那里拿到物品。我们需要保证:如果在操作的过程中出了差错, 那么所有这些步骤都不会发生效果。把这些更新组合成一个事务就给予我们这样的保证。 事务被认为是原子的:从其它事务的角度来看,它要么是全部发生,要么完全不发生。
我们还需要保证:一旦一个事务完成并且得到数据库系统的认可, 那么它必须被真正永久地存储,并且不会在随后的崩溃中消失。 比如,如果我们记录到了一个 Bob 撤单的动作, 那么我们不希望仅仅在他走出银行大门之后的一次崩溃就会导致对他的帐户的扣减动作消失。 一个事务型数据库保证一个事务所做的所有更新在事务发出完成响应之前都记录到永久的存储中(也就是磁盘)。
事务型数据库的另外一个重要的性质和原子更新的概念关系密切: 当多个事务并发地运行的时候,那么每个事务都不应看到其它事务所做的未完成的变化。 比如,如果一个事务正忙着计算所有分行的余额总和, 那么它不应该包括来自 Alice 的分行的扣帐和来自 Bob 分行的入帐,反之亦然。 所以事务必须是黑白分明的,不仅仅体现在它们在数据库上产生的永久影响出发,而且体现在它们运转时的自身的可视性上。 一个打开的事务做的更新在它完成之前是其它事务无法看到的,而到提交的时候所有更新同时可见。
在 PostgreSQL 里,一个事务是通过把 SQL 命令用 BEGIN 和 COMMIT 命令包围实现的。 因此我们的银行事务实际上看起来象下面这样
BEGIN;
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
-- 等等
COMMIT;
如果在该事务的过程中,我们决定不做提交(可能是我们刚发现 Alice 的余额是负数), 那么我们可以发出 ROLLBACK 命令而不是 COMMIT 命令,那么到目前为止我们的所有更新都会被取消。
PostgreSQL 实际上把每个 SQL 语句当做在一个事务中执行的来看待。 如果你没有发出 BEGIN 命令,那么每个独立的语句都有一个隐含的 BEGIN 和(如果成功的话) COMMIT 语句包围在周围。 一组包围在 BEGIN 和 COMMIT 语句中间的语句有时候被称做事务块。
注意: 一些客户库自动发出 BEGIN 和 COMMIT, 因此你可能不需要特意请求就可以获取事务块的效果。查看你使用的接口的文档。
我们可以通过使用 savepoints 的方法,在一个事务里更加精细地控制其中的语句。 保存点允许你有选择性地抛弃事务中的某些部分,而提交其它剩下的。 在用 SAVEPOINT 定义了一个保存点后,如果需要,你可以使用 ROLLBACK TO 回滚到该保存点。 则该事务在定义保存点到回滚到它之间的所有数据库更改都被抛弃,但是在保存点之前的修改将被保留。
在回滚到一个保存点之后,这个保存点仍然保存着其定义,所以你可以回滚到这个位置好几次。 当然,如果你确信你不需要再次回滚到一个保存点,那么你可以释放它,这样系统可以释放一些资源。 要记住:释放或者回滚到一个保存点都会自动释放在其后定义的所有保存点。
所有这些都发生在一个事务块内部,所以所有这些都不可能被其它事务会话看到。 当且仅当你提交了这个事务块,这些提交了的动作才能以一个单元的方式被其它会话看到, 而回滚的动作完全不会再被看到。
还记得我们的银行数据库吗?假设我们从 Alice 的帐户上消费 $100.00, 然后给 Bob 的帐户进行贷记加款,稍后我们发现我们应该给 Wally 的账号贷记加款。 那么我们可以像下面这样的保存点来做:
BEGIN;
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
SAVEPOINT my_savepoint;
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Bob';
-- 呀!加错钱了,应该用 Wally 的账号
ROLLBACK TO my_savepoint;
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Wally';
COMMIT;
这个例子当然是实在太简单了,但是通过使用保存点,我们可以对事务块有大量的控制。 并且,ROLLBACK TO 是除了事务全部回滚,重新来过之外的唯一可用的, 用于重新控制一个因错误而被系统置于退出状态下的事务的方法。
分享到:
相关推荐
本文介绍了Oracle 事务概念和知识。在测试通过的基础上,采用讲解结合实例的方式,对Oracle 事务概念和知识进行了说明和讲解,并对关键知识点进行了标注,读者只需按照本文内容逐步进行学习和操作,即可完成Oracle...
本书主要阐述事务概念是如何用于解决分布式系统问题的,以及这些概念如何使我们能够在有限的资金和风险范围内建立高性能、高可用性的应用系统。本书内容广泛,从系统的角度全面阐述事务处理的概念和技术,涉及终端上...
如果你正在学hibernate框架,我认为这份文档对你会有很大的关系。 如果你真的需要可以下载啊,积分又不是很多是吧,关键能学到知识就行了
本文实例讲述了MySQL 事务概念与用法。分享给大家供大家参考,具体如下: 事务的概念 MySQL事务是一个或者多个的数据库操作,要么全部执行成功,要么全部失败回滚。 事务是通过事务日志来实现的,事务日志包括:redo...
NULL 博文链接:https://huiqinbo.iteye.com/blog/2247535
数据库事务:对数据库事务的讲解,事务的概念 理解事务的特性、分类
事务的基本概念和在不同环境下如何使用事务。
) .findAndModify node.js 中 mongodb 事务概念的证明。用法 $ git clone git@github.com:rusintez/mongodb-transactions.git mt$ cd mt$ npm install$ node index.js应用程序接口 var transaction = require ( './...
事务处理概念与技术
主要介绍了MySQL中的事务概念,是MySQL入门学习中的基础知识,需要的朋友可以参考下
事务处理 概念与技术
本章首先介绍客户-服务器事务概念。我们从使用U D P的客户-服务器应用开始,这是最 简单的情形。接着我们编写使用T C P的客户和服务器程序,并由此考察两台主机间交互的 T C P / I P分组。然后我们使用T / T C P,...
GBase 8s事务相关概念
事务概念、ACID原则、事务注解
数据库系统是一个共享系统,会有很多用户同时访问同一数据,例如,订票系统中多个用户同时访问飞往北京的同一航班...本章先讨论事务概念和基本性质,然后再利用事务处理技术来研究数据操作并发控制与数据库的故障恢复。
这是一部关于事务的作品,书中讲述了事务的一些基础知识,包括如果实现事务,做了一些讲解
要求学生加深对数据库并发控制,封锁机制和事务概念的理解,掌握事务的定义,使用方法,能够使用事务对数据库进行简单的并发操作。