银行的那些事
银行应用是解释事务必要性的一个经典例子。假设一家银行的数据库有两张表:支票(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的实现。
这就像锁粒度一样,会增加系统开销,这种事务处理过程中的额外的安全性,也需要数据库系统做更多的额外工作。
事务隔离
https://baijiahao.baidu.com/s?id=1611918898724887602&wfr=spider&for=pc
一般的数据库,都包括以下四种隔离级别:
- 读未提交(Read Uncommitted):可以读到未提交的内容
- 读提交(Read Committed):只能读到已经提交了的内容(大部分)
- 可重复读(Repeated Read):MySql的默认隔离级别;专门针对“不可重复读”这种情况而制定的隔离级别
- 串行化(Serializable):数据库最高的隔离级别;就是事务一个一个排队执行
脏读(读取事务未提交数据)
不可重复读(前后多次读取,数据内容不一致)
幻读(前后多次读取,数据总量不一致)