NESTED 嵌套事务在数据库里到底是什么?它比普通加入外层事务贵多少?为什么用 JPA 的时候 NESTED 会直接报错?这篇在 Spring Framework 7.0.9、Hibernate 和 MySQL 26.7.0 上把语句和报错逐条量出来。
inner 成功:提交后表里的行 outer-1+inner+outer-2;那个连接上的语句:
SET autocommit=0
insert into t(v) values ('outer-1')
SAVEPOINT `SAVEPOINT_1`
insert into t(v) values ('inner')
RELEASE SAVEPOINT `SAVEPOINT_1`
insert into t(v) values ('outer-2')
COMMIT
SET autocommit=1
inner 失败:提交后表里的行 outer-1+outer-2;那个连接上的语句:
SET autocommit=0
insert into t(v) values ('outer-1')
SAVEPOINT `SAVEPOINT_1`
insert into t(v) values ('inner')
ROLLBACK TO SAVEPOINT `SAVEPOINT_1`
RELEASE SAVEPOINT `SAVEPOINT_1`
insert into t(v) values ('outer-2')
COMMIT
SET autocommit=1NESTED 在同一个连接上用 SAVEPOINT 和 ROLLBACK TO SAVEPOINT 实现。
一个事务里调用内层方法 2000 次:REQUIRED 132 ms(每次 66 µs);NESTED 358 ms(每次 179 µs) 一个事务里调用内层方法 2000 次:REQUIRED 269 ms(每次 135 µs);NESTED 791 ms(每次 396 µs) 一个事务里调用内层方法 2000 次:REQUIRED 128 ms(每次 64 µs);NESTED 300 ms(每次 150 µs)
每次多两条语句,耗时是 REQUIRED 的两倍多。
JpaTransactionManager(setNestedTransactionAllowed(false))+ Hibernate 里调用 NESTED 方法 → NestedTransactionNotSupportedException: Transaction manager does not allow nested transactions by default - specify 'nestedTransactionAllowed' property with value 'true' JpaTransactionManager(setNestedTransactionAllowed(true))+ Hibernate 里调用 NESTED 方法 → NestedTransactionNotSupportedException: JpaDialect does not support savepoints - check your JPA provider's capabilities
JpaTransactionManager 默认不允许,打开后 Hibernate 的 JpaDialect 也不支持 savepoint。