银行的那些事
银行应用是解释事务必要性的一个经典例子。假设一家银行的数据库有两张表:支票(checking)表和储蓄(savings)表。现在客户葫芦爷爷要从支票账户转移200美元到储蓄账户,那么需要至少三步:
- 检查支票账户的余额高于200美元。
- 从支票账户余额中减去200美元。
- 从储蓄账户的余额中增加200美元。
上述三个步骤必须打包在一个事务当中,任何一个步骤失败,则必须所有步骤全部失败回滚。
第一步-- start transaction;第二步-- select balance from checking where customer_id=1022376;第三步-- update checking set balance=balance-200.00 where customer_id=1022376;第四步-- update savings set blance=balance+200.00 where customer_id=1022376;第五步-- commit / rollback ;
单纯的事务并不是故事的全部。设想一下;如果执行到第四步操作时服务器崩溃了,会发生什么?天知道用户可能会损失200美元。
除非系统通过严格的ACID测试。ACID 即包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability);指数据库事务正确执行的四个基本要素;
原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。
一致性(consistency)
数据库总是从一个一致性的状态转换到另一个一致性的状态。在前面的例子当中,一致性确保了即使在执行第三四条语句时系统崩溃,支票账户也不会损失200 美元,
隔离性(isolation)
通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的。在前面的例子当中,当执行完第三条语句,而第四条语句还未执行时,此时另外一个账户汇总程序开始运行,则看到支票账户的余额并没有减去200美元。
持久性(durability)
一旦事务提交则其所做的改变就会永久的保存到数据库中,以供下一次增删改查操作。
但是
事务的ACID特性可以确保银行不会弄丢葫芦爷爷的钱。而在应用逻辑中,要实现这一点非常难,甚至可以说是不可能完成的任务,一个兼容ACID的系统,需要做很多复杂但可能用户并没有察觉的操作,才能确保ACID的实现。
这就像锁粒度一样,会增加系统开销,这种事务处理过程中的额外的安全性,也需要数据库系统做更多的额外工作。