spring如何处理事务呢?下面是个伪代码示意:
begin Transactional;
try{
//TODO
commit;
}catch (Throwable e){
if(e属于该提交的(即noRollbackFor指定)的异常类型){
commit;
}else {
rollback;
}
}
如果要配置全局事务管理,参考这篇文章全局性事务控制如何在springboot中配置
/**
* Support a current transaction, create a new one if none exists.
* This is the default setting of a transaction annotation.
*/
/**
* Support a current transaction, execute non-transactionally if none exists.
* Note: For transaction managers with transaction synchronization,
* PROPAGATION_SUPPORTS is slightly different from no transaction at all,
* as it defines a transaction scope that synchronization will apply for.
* As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
* will be shared for the entire specified scope. Note that this depends on
* the actual synchronization configuration of the transaction manager.
*/
/**
* Create a new transaction, suspending the current transaction if one exists.
* NOTE: Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
*
A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
*/
/**
* Do not support a current transaction; rather always execute non-transactionally.
* NOTE: Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
*
Note that transaction synchronization is not available within a
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
* will be suspended and resumed appropriately.
*/
/**
* Support a current transaction, throw an exception if none exists.
* Analogous to EJB transaction attribute of the same name.
*/
/**
* Execute non-transactionally, throw an exception if a transaction exists.
*/
/**
* Execute within a nested transaction if a current transaction exists,
* behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.
* Note: Actual creation of a nested transaction will only work on specific
* transaction managers. Out of the box, this only applies to the JDBC
*/
嵌套事务中发生异常会回滚到savePoint,不对主事务之前的操作产生影响,但提交还要依赖主事务的成功。
A constant indicating that dirty reads, non-repeatable reads and phantom reads
* can occur. This level allows a row changed by one transaction to be read by
* another transaction before any changes in that row have been committed
* (a "dirty read"). If any of the changes are rolled back, the second
* transaction will have retrieved an invalid row.
A constant indicating that dirty reads are prevented; non-repeatable reads
* and phantom reads can occur. This level only prohibits a transaction
* from reading a row with uncommitted changes in it.
A constant indicating that dirty reads and non-repeatable reads are
* prevented; phantom reads can occur. This level prohibits a transaction
* from reading a row with uncommitted changes in it, and it also prohibits
* the situation where one transaction reads a row, a second transaction
* alters the row, and the first transaction rereads the row, getting
* different values the second time (a "non-repeatable read").
A constant indicating that dirty reads, non-repeatable reads and phantom
* reads are prevented. This level includes the prohibitions in
* {@code ISOLATION_REPEATABLE_READ} and further prohibits the situation
* where one transaction reads all rows that satisfy a {@code WHERE}
* condition, a second transaction inserts a row that satisfies that
* {@code WHERE} condition, and the first transaction rereads for the
* same condition, retrieving the additional "phantom" row in the second read.
幻读和不可重复读相似容易混淆,幻读指的是第一个事务相同查询条件的查询行数,另一个事务增加或删除了某行(inserts a row),导致第一个事务两次查询的结果不同。不可重复读指的是另一个事务修改( alters the row)了某行的数据。
隔离和锁是不同的东西,隔离不是靠锁实现,是根据对数据的监控实现的,相比锁会回滚事务。
如果事务超过时间限制还没完成,就会回滚。
从方法执行开始计算。每个sql执行前检查一次是否超时,方法全部执行完毕后不检查是否超时。即设置事务超时为10秒,即使整个方法耗时20秒也不一定超时。
假设事务超时时间设置为2秒;假设sql执行时间为1秒;
如下调用是事务不超时的
public void testTimeout() throws InterruptedException {
System.out.println(System.currentTimeMillis());
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
jdbcTemplate.execute(" update test set hobby = hobby || '1'");
System.out.println(System.currentTimeMillis());
Thread.sleep(3000L);
}
而如下事务超时是起作用的:
public void testTimeout() throws InterruptedException {
Thread.sleep(3000L);
System.out.println(System.currentTimeMillis());
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
jdbcTemplate.execute(" update test set hobby = hobby || '1'");
System.out.println(System.currentTimeMillis());
}
參考博客
注意 在只读事务中修改数据库是会报错的!