一、之前对事物的了解只是停留在声明式事物,配置xml,或使用注解,事物的传播行为也只用过REQUIRED和SUPPORTS,能够说对事物的了解很模糊。java
二、直到在开发中遇到问题。。spring
问题的描述是:编程
年末跑定时任务,获取用户年末过时积分,并发送积分即将过时的消息提示;缓存
过时积分作记录,并与积分作关联记录,涉及两表的操做;springboot
数据量较多,循环保存,要作到每次循环都会手动提交,而不是作缓存最后提交;并发
事物的传播行为为默认的REQUIRED,二两个表操做涉及到了嵌套事物;ide
So。。。优化
解决办法:spa
1声明式事物方式.net
@Transactional(propagation = Propagation.REQUIRES_NEW)
2采用了编程式事物
事物的传播行为选择为:PROPAGATION_REQUIRES_NEW
public boolean updateExpireCredit(Credit credit) throws Exception { // 事务开始-方法级别 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // 传播行为: 新建事务,若是当前存在事务,把当前事务挂起 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); def.setTimeout(30); // 事务状态 TransactionStatus status = tm.getTransaction(def); boolean falg = false; try { creditRepository.save(credit); tm.commit(status); falg = true; } catch (Exception e) { e.printStackTrace(); log.error("出现异常,事务回滚:{}", e); if (!status.isCompleted()) { tm.rollback(status); } throw e; } return falg; }
PlatformTransactionManager
jdbc——org.springframework.jdbc.datasource.DataSourceTransactionManager
hibernate——HibernateTransactionManager
jpa——org.springframework.orm.jpa.JpaTransactionManager
java的jta——org.springframework.transaction.jta.JtaTransactionManager
TransactionDefinition接口内容以下:
public interface TransactionDefinition { int getPropagationBehavior(); // 返回事务的传播行为 int getIsolationLevel(); // 返回事务的隔离级别,事务管理器根据它来控制另一个事务能够看到本事务内的哪些数据 int getTimeout(); // 返回事务必须在多少秒内完成 boolean isReadOnly(); // 事务是否只读,事务管理器可以根据这个返回值进行优化,确保事务是只读的 }
注:PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 彻底是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 若是外部事务 commit, 嵌套事务也会被 commit, 这个规则一样适用于 roll back.
在同一个应用程序或者不一样应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。
并发事务所致使的问题能够分为如下三类:
① 脏读:脏读发生在一个事务读取了另外一个事务改写但尚未提交的数据时。若是改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
② 不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,可是每次都获得不一样的数据时。这一般是由于另外一个并发事务在两次查询期间更新了数据
③ 幻读:幻读与不可重复读相似。它发生在一个事务(T1)读取了几行数据,接着另外一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些本来不存在的记录
注:
不可重复读的重点是修改
幻读的重点在于新增或者删除
PlatformTransactionManager接口的getTransaction()的方法获得的是TransactionStatus接口的一个实现,这个接口的内容以下:
public interface TransactionStatus{ boolean isNewTransaction(); // 是不是新的事物 boolean hasSavepoint(); // 是否有恢复点 void setRollbackOnly(); // 设置为只回滚 boolean isRollbackOnly(); // 是否为只回滚 boolean isCompleted; // 是否已完成 }
6.编程时事物和声明式事物