事务是什么?

引言

软件开发领域里,全有或者全无的操作被称为[事务] 例如,买电影票这件事,可能需要以下几个步骤:

  • 检查可售出的座位,确保买到票的人能有座位
  • 每卖出一张票,空闲座位数就减少一个
  • 为购买的电影票进行支付
  • 将电影票分配给你 这个流程用事务管理就是: ![事务管理示意图](pic/transaction.png)

这样,就可以确保购票者和影院都没有损失,即,用户不会买到没有座位的票,影院也不会有用户买到票了却没有收到钱等情况出现

事务的四个特性

  • 原子性(Atomic) 即确保事务内的一个或者多个活动全部发生或全部不发生。如果事务内的活动均成功,则事务成功;如果有失败,则事务失败并回滚。
  • 一致性(Consistent) 一旦事务完成,不论成功还是失败,业务内的数据应处于一致的状态。
  • 隔离性(Isolated) 事务允许多个用户对相同的数据进行读写,事务应该彼此隔离,避免发生同步读写相同数据的事情
  • 持久性(Durable) 一旦事务完成,结果应该被持久化,以保证在出现系统崩溃等情况时的恢复能力

其实,这几个特性是互相保证的,原子性通过保证系统数据永远不会处于不一致或部分完成的状态来确保一致性,隔离性也同样保证了一致性。持久性保证了事务的结果不会丢失。

Spring 对事务管理的支持

编码方式管理事务

暂略

声明方式管理事务

事务的5种属性

传播行为

传播行为的以下几种规则回答了这样一个问题:即新的事务应该被启动还是被刮起,或者方法是否要在事务环境中运行。

传播行为 含义
PROPOGATION_MANDATORY 表示当前方法必须在事务中运行,如果事务不存在,则会抛出一个异常
PROPOGATION_NESTED 如果已经存在事务,则在嵌套事务中运行,可独立于已存在的事务单独地提交或者回滚;如果当前事物不存在,则与PROPOGATION_REQUIERED一样
PROPOGATION_NEVER 表示当前方法不应该运行在事务上下文中,如果当前正有一个事务正在运行,则会抛出异常
PROPOGATION_NOT_SUPPORTED 表示当前方法不应该运行在事务中,如果当前存在事务,则在该方法运行期间被挂起
PROPOGATION_REQUIRED 表示当前方法必须在事务中,如果当前事务存在,方法将会在该事务中运行;如果当前事务不存在,会启动一个新的事务
PROPOGATION_REQUIRES_NEW 表示当前方法必须运行在它自己的事务中,一个新的事务将被启动,如果存在当前事务,则在该方法执行期间,当前事务会被挂起
PROPOGATION_SUPPORTS 表示当前方法不需要运行在事务上下文中,但如果存在当前事务的话,那么该方法会在这个事务中运行

隔离级别

隔离级别 含义 说明
ISOLATION_DEFAULT 默认 使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED 读未提交 脏读,不可重复读,幻读都有可能出现,效率最高
ISOLATION_READ_COMMITTED 读已提交 可避免脏读
ISOLATION_REPEATABLE_READ 可重复读 可避免脏读,不可重复读
ISOLATION_SERIALIZABLE 序列化 完全服从ACID的隔离级别,效率最低

是否只读?

如果事务只对后端数据库进行读的操作,数据库可以利用事务的只读特性进行一些特定的优化 注:只有传播行为为:PROPOGATION_NESTED/PROPOGATION_REQUIRED/PROPOGATION_REQUIRES_NEW的方法来说,将事务声明为只读才有意义

事务回滚规则

默认情况下,事务只有在遇到运行时异常才会回滚,遇到检查型异常时不会回滚 但是,可以通过配置实现制定具体事务回滚规则

事务超时

为了使程序能更好的运行,事务不能运行太久的时间,因此事务的超时特性也很重要 注:也只在传播行为为PROPOGATION_NESTED/PROPOGATION_REQUIRED/PROPOGATION_REQUIRES_NEW的方法来说有意义

在XML中定义事务

未完待续。。。