事物脚本:将所有逻辑组织成单个过程,在过程中直接调用数据库,或者只通一个简单的数据库封装器。
可以用两种方法来把事务脚本组织成类。1.将数个脚本放在一个类中,每个类围绕一个主题将相关的事务脚本组织在一起。另一种方法是每一个事务脚本对应一个类,此时需使用命令模式。大多数情况下,每一个数据库事务对应一个事务脚本。
使用时机:
事务脚本胜在简单,对于只有少量逻辑的应用程序来说,使用这一模式非常自然,无论在性能上还是理解上都不会带来太大的开销。但是,当业务逻辑越来越复杂时,使用这一模式就会越来越难以保持良好的设计。它特有的问题是事务之间的冗余代码。谨慎提取公共子程序可以避免很多问题,但更复杂的业务领域则需要建立领域模型。
并发问题:
l 更新丢失:
A开始编辑Z
B开始编辑Z
B保存Z
A保存Z
A保存Z时,B的所有改动被覆盖,永远丢失了。
l 不一致读:
A要读两个包:Y包原有7个类,Z包原有5个类。
A读Y包,得到7个类。
B向Y包加2个类(此时Y包有9个类)
B向Z包加3个类(此时Z包有8个类)
A读Z包,得到8个类。于是A的结果是Y、Z两个包一共7+8=15类。
但正确的是:B更新前的12个类或B更新后的17个类。
l 乐观并发控制:
A、B均可以编辑同一个文件Z。A可以先保存Z,当B后保存Z时,就要B指定如何处理这种情况。
l 悲观并发控制:
如果A打开文件Z,则B不能打开文件Z。
软件“事务”经常使用ACID属性来描述:
l 原子性(Atomicity):在一个事务里,动作序列的每一个步骤都必须要么全部成功,要么所有的工作都将回滚。部分完成不是一个事务概念。
l 一致性(Consistency):在事务开始和完成的时候,系统的资源都必须处于一致的、没有被破坏的状态。
l 隔离性(Isolation):一个事务,直到它被成功提交之后,它的结果对于任何其他的事务才是可见的。
l 持久性(Duralility):一个已提交事务的任何结果都必须是永久性的,即“在任何系统崩溃的情况下都能保存下来。”。