Spring 使用 AOP 来完成宣告式的交易管理,因而宣告式交易是以方法为单位,Spring 的交易属 性(Transaction attribute)自然就在于描述交易应用至方法上的策略,在 Spring 中交易属性 可设定以下的几个参数:
• 传播行为(Propagation behavior)
传播行为定义了交易应用于方法上之边界(Boundaries),它告知何时该开始一个新的交易,或 何时交易该被暂停,或者方法是否要在交易中进行。
Spring 定义几个传播行为,可在 TransactionDefinition 的 API 文件说明上找到相对应的常数 与说明,以下列出几个:
传播行为 | 说明 |
---|---|
PROPAGATION_MANDATORY |
方法必须在一个现存的交易中进行,否则丢出例外 |
PROPAGATION_NESTED |
在一个巢状的交易中进行,如果不是的话,则同 |
PROPAGATION_NEVER |
指出不应在交易中进行,如果有的话就丢出例外 |
PROPAGATION_NOT_SUPPORTED |
指出不应在交易中进行,如果有的话就暂停现存的交易 |
PROPAGATION_REQUIRED |
支援现在的交易,如果没有的话就建立一个新的交易 |
PROPAGATION_REQUIRES_NEW |
建立一个新的交易,如果现存一个交易的话就暂停它 |
PROPAGATION_SUPPORTS |
支援现在的交易,如果没有的话就以非交易的方式执行 |
举个例子来说,如果传播行为被宣告为 PROPAGATION_REQUIRED,则交易的边界在于第一个开始 交易的方法呼叫及结束时,如果先前没有交易被开始,则交易边界即为目前的方法呼叫 前后。 又如果传播行为被宣告为 PROPAGATION_REQUIRES_NEW,则交易的边界即为该方法呼叫的前后。
• 隔离层级(Isolation level)
在一个应用程式中,可能有多个交易同时在进行,这些交易应当彼此之间互相不知道另一个交易 的存在,好比现在整个应用程式就只有一个交易存在的样子,由于交易彼此之间独立,若读取的 是同一个资料的话,就容易发生问题,例如:
o Dirty read
某个交易已更新一份资料,另一个交易在此时读取了同一份资料,由于某些原因,前一个交易回 滚(Roll back)了操作,则后一个交易所读取的资料就会是不正确的。
o Non-repeatable read
在一个交易的两次查询之中资料不一致,可能因为两次查询过程中间插入了一个交易更新的原有 的资料。
o Phantom read
在一个交易的两次查询中资料笔数不一致,例如有一个交易查询了几列(Row)资料,而另一个 交易却在此时插入了新的几列数据,先前的交易在接下来的查询中,就会发现有几列数据是它先 前所没有的。
为了避免以上问题的方法之一,就是在某个交易进行过程中锁 定正在更新或查询的资料栏位, 直到目前的交易完成,然而完全的锁定栏位时,另一个交易来进行查询同一份资料时就必须等待, 直到前一个交易完成并解除锁定为 止,因而会造成应用程式在查询或更新资料时效能上的问题, 而事实上根据需求的不同,并不用在交易进行时完全的锁定资料,隔离层级让您根据实际的需求, 对资 料的锁定进行设置。
Spring 提供了几种隔离层级设定,同样的可以在 TransactionDefinition 的 API 文件说明上找 到相对应的常数与说明,以下列出几个:
隔离层级 |
说明 |
|
|
ISOLATION_DEFAULT |
使用底层资料库预设的隔离层级 |
ISOLATION_READ_COMMITTED |
允许交易读取其它并行的交易已经送出(Commit)的资料栏 位,可以防止 Dirty read 问题 |
ISOLATION_READ_UNCOMMITTED |
允许交易读取其它并行的交易还没送出的资料,会发生 Dirty |
ISOLATION_REPEATABLE_READ |
要求多次读取的资料必须相同,除非交易本身更新资料,可防 止 Dirty、Nonrepeatable read 问题 |
ISOLATION_SERIALIZABLE |
完整的隔离层级,可防止 Dirty、Nonrepeatable、Phantom read |
• 唯读提示(Read-only hints)
如果交易只进行读取的动作,则可以利用底层资料库在唯读操 作时的一些最佳化动作,由于这 个动作利用到资料库在唯读的交易操作最佳化,因而必须在交易中才有效,也就是说您要搭配传 播行为 PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、 PROPAGATION_NESTED 来设置。
• 交易超时期间(The transaction timeout period)
有的交易操作可能延续一段很长的时间,交易本身可能关联到资料表格的锁定,因而长时间的交 易操作会有效能上的问题,对于过长的交易操作,您要考虑回滚(Roll back)交易并要求重新 操作,而不是无限时的等待交易完成。
您可以设置交易超时期间,计时是从交易开始时,所以这个设置必须搭配传播行为 PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED 来设置。