Spring面试题及详细答案 125道(46-65) -- 事务管理
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。

文章目录
- 一、本文面试题目录
- 46. Spring事务管理的核心接口有哪些?
- 47. 什么是声明式事务?什么是编程式事务?各有什么优缺点?
- 48. Spring事务的传播行为有哪些?请解释各自的含义。
- 49. Spring事务的隔离级别有哪些?和数据库的隔离级别有什么关系?
- 50. 如何在Spring中配置声明式事务?(基于XML和注解)
- 51. @Transactional注解的常用属性有哪些?
- 52. 什么情况下Spring事务会失效?
- 53. 如何实现分布式事务?Spring对分布式事务有哪些支持?
- 54. 请解释事务的ACID特性。
- 55. 什么是脏读、不可重复读、幻读?如何通过隔离级别避免?
- 56. Spring事务管理中,如何指定事务的回滚规则?
- 原理说明:
- 示例代码:
- 57. 只读事务的作用是什么?
- 原理说明:
- 示例代码:
- 注意:
- 58. 嵌套事务和事务传播行为中的NESTED有什么关系?
- 关系说明:
- 示例代码:
- 59. 如何在Spring中使用编程式事务?
- 原理说明:
- 示例代码:
- 60. Spring事务同步机制是什么?
- 原理说明:
- 示例代码:
- 应用场景:
- 61. @Transactional注解的 propagation=REQUIRES_NEW 和 NESTED 有什么区别?
- 示例代码:
- 62. 为什么说事务的隔离级别越高,性能可能越低?
- 原因分析:
- 总结:
- 63. 如何在Spring中实现事务的手动回滚?
- 实现方式:
- 64. 多线程环境下,Spring事务会出现什么问题?如何解决?
- 问题说明:
- 解决方式:
- 65. 什么是事务的超时时间?如何配置?
- 配置方式:
- 注意:
一、本文面试题目录
46. Spring事务管理的核心接口有哪些?
Spring事务管理的核心接口如下:
-
PlatformTransactionManager(平台事务管理器)
事务管理的核心接口,定义了事务的基本操作(获取、提交、回滚),不同的数据源(如JDBC、Hibernate)有不同实现:DataSourceTransactionManager
:用于JDBC或MyBatis的事务管理。HibernateTransactionManager
:用于Hibernate的事务管理。JpaTransactionManager
:用于JPA的事务管理。
核心方法:
TransactionStatus getTransaction(TransactionDefinition definition); // 获取事务 void commit(TransactionStatus status); // 提交事务 void rollback(TransactionStatus status); // 回滚事务
-
TransactionDefinition(事务定义)
定义事务的属性(隔离级别、传播行为、超时时间、是否只读),常用实现类为DefaultTransactionDefinition
。 -
TransactionStatus(事务状态)
代表当前事务的运行状态,提供事务是否活跃、是否已提交、是否需要回滚等信息。
47. 什么是声明式事务?什么是编程式事务?各有什么优缺点?
-
声明式事务
通过注解(如@Transactional
)或XML配置声明事务规则,无需手动编写事务控制代码,由Spring自动管理事务。- 优点:
- 非侵入式,业务代码与事务逻辑分离,代码简洁。
- 配置灵活,便于统一管理和修改。
- 缺点:
- 细粒度控制能力较弱(如部分代码需要事务,部分不需要)。
- 异常处理依赖默认规则,自定义回滚逻辑较复杂。
- 示例:
@Service public class OrderService {@Transactional // 声明式事务public void createOrder() {// 业务逻辑(自动纳入事务管理)} }
- 优点:
-
编程式事务
通过手动编写代码控制事务(如TransactionTemplate
或PlatformTransactionManager
),显式定义事务的开始、提交和回滚。- 优点:
- 细粒度控制,可精确控制事务范围(如条件性提交/回滚)。
- 灵活度高,支持复杂的事务逻辑。
- 缺点:
- 侵入业务代码,事务逻辑与业务逻辑混杂。
- 代码冗余,重复编写事务控制代码。
- 示例:
@Service public class OrderService {@Autowiredprivate TransactionTemplate transactionTemplate;public void createOrder() {transactionTemplate.execute(status -> { // 编程式事务try {// 业务逻辑return true;} catch (Exception e) {status.setRollbackOnly(); // 手动回滚return false;}});} }
- 优点:
48. Spring事务的传播行为有哪些?请解释各自的含义。
事务传播行为定义了多个事务方法相互调用时,事务的传播规则。Spring定义了7种传播行为:
-
PROPAGATION_REQUIRED(默认)
如果当前存在事务,则加入该事务;如果没有事务,则创建新事务。@Transactional(propagation = Propagation.REQUIRED) public void methodA() { methodB(); } // methodA和methodB在同一事务中@Transactional(propagation = Propagation.REQUIRED) public void methodB() {}
-
PROPAGATION_SUPPORTS
如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。 -
PROPAGATION_MANDATORY
必须在已存在的事务中执行,否则抛出IllegalTransactionStateException
。 -
PROPAGATION_REQUIRES_NEW
无论当前是否存在事务,都创建新事务(原事务暂停,新事务执行完毕后恢复原事务)。@Transactional(propagation = Propagation.REQUIRED) public void methodA() { methodB(); } // methodA的事务与methodB的事务独立@Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB() {}
-
PROPAGATION_NOT_SUPPORTED
以非事务方式执行,如果当前存在事务,则暂停该事务。 -
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。 -
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务中执行(嵌套事务依赖于外层事务,外层回滚则嵌套事务也回滚);如果没有事务,则创建新事务。
49. Spring事务的隔离级别有哪些?和数据库的隔离级别有什么关系?
-
Spring事务的隔离级别(定义在
Isolation
枚举中):- DEFAULT(默认):使用数据库默认的隔离级别(如MySQL默认REPEATABLE_READ,Oracle默认READ_COMMITTED)。
- READ_UNCOMMITTED:允许读取未提交的数据(可能导致脏读、不可重复读、幻读)。
- READ_COMMITTED:只能读取已提交的数据(避免脏读,可能导致不可重复读、幻读)。
- REPEATABLE_READ:保证多次读取同一数据结果一致(避免脏读、不可重复读,可能导致幻读)。
- SERIALIZABLE:最高隔离级别,完全避免并发问题(但性能极低)。
-
与数据库隔离级别的关系:
- Spring的隔离级别是对数据库隔离级别的封装,最终由数据库实现(Spring不直接提供隔离能力)。
- 若Spring配置的隔离级别数据库不支持,会抛出异常(如MySQL不支持SERIALIZABLE时强制使用会报错)。
- 示例(指定隔离级别):
@Transactional(isolation = Isolation.READ_COMMITTED) public void queryData() {// 事务隔离级别为READ_COMMITTED }
50. 如何在Spring中配置声明式事务?(基于XML和注解)
-
方式1:基于注解配置
- 启用事务注解支持:
@Configuration @EnableTransactionManagement // 启用声明式事务 public class TxConfig {// 配置数据源@Beanpublic DataSource dataSource() {// 数据源配置(如HikariCP)}// 配置事务管理器@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);} }
- 在业务方法上添加
@Transactional
:@Service public class UserService {@Transactional // 该方法纳入事务管理public void updateUser(Long id, String name) {// 数据库操作} }
- 启用事务注解支持:
-
方式2:基于XML配置
<!-- 配置数据源 --> <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="123456"/> </bean><!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean><!-- 配置事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="add*" propagation="REQUIRED"/> <!-- 匹配add开头的方法 --><tx:method name="update*" propagation="REQUIRED"/><tx:method name="*" read-only="true"/> <!-- 其他方法只读 --></tx:attributes> </tx:advice><!-- 配置AOP切入点 --> <aop:config><aop:pointcut id="txPointcut" expression="execution(* com.example.service.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>
51. @Transactional注解的常用属性有哪些?
@Transactional
注解的常用属性如下:
- propagation:事务传播行为(默认
REQUIRED
),如propagation = Propagation.REQUIRES_NEW
。 - isolation:事务隔离级别(默认
DEFAULT
),如isolation = Isolation.READ_COMMITTED
。 - readOnly:是否为只读事务(默认
false
),查询操作可设为true
提升性能:@Transactional(readOnly = true) public List<User> queryUsers() { ... }
- timeout:事务超时时间(单位:秒,默认-1表示无超时),超时后自动回滚:
@Transactional(timeout = 30) // 30秒超时 public void longRunningTask() { ... }
- rollbackFor:指定触发回滚的异常类型(默认仅回滚
RuntimeException
及其子类):@Transactional(rollbackFor = {SQLException.class, IOException.class}) public void saveData() { ... }
- noRollbackFor:指定不触发回滚的异常类型:
@Transactional(noRollbackFor = BusinessException.class) public void process() { ... }
- value/transactionManager:指定事务管理器(多数据源时使用)。
52. 什么情况下Spring事务会失效?
Spring事务失效的常见场景如下:
-
1. 方法未被Spring管理
若类未被@Service
、@Component
等注解标记(未纳入Spring容器),@Transactional
无效。// 错误:未被Spring管理 public class UserService {@Transactionalpublic void update() { ... } }
-
2. 方法不是public
@Transactional
仅对public方法生效(非public方法的注解会被忽略)。@Service public class UserService {@Transactionalprivate void update() { ... } // 私有方法,事务失效 }
-
3. 自身调用(未通过代理对象)
同一类中方法A调用方法B,若B有@Transactional
而A没有,B的事务失效(因未经过代理)。@Service public class UserService {public void methodA() {methodB(); // 自身调用,methodB的事务失效}@Transactionalpublic void methodB() { ... } }
-
4. 异常被捕获且未重新抛出
若方法内捕获异常且未抛出,Spring无法感知异常,不会触发回滚。@Transactional public void update() {try {// 数据库操作} catch (Exception e) {// 错误:未抛出异常,事务不回滚} }
-
5. 异常类型不匹配
默认仅回滚RuntimeException
,若抛出检查型异常(如IOException
)且未指定rollbackFor
,事务不回滚。@Transactional // 未指定rollbackFor,下面的异常不会触发回滚 public void update() throws IOException {throw new IOException(); }
-
6. 错误的传播行为
如使用PROPAGATION_NOT_SUPPORTED
(非事务方式执行)会导致事务失效。
53. 如何实现分布式事务?Spring对分布式事务有哪些支持?
分布式事务是指跨多个数据库或服务的事务,需保证ACID特性。常见实现方案及Spring支持如下:
-
1. 2PC(两阶段提交)
- 原理:分准备阶段(所有参与者确认可提交)和提交阶段(协调者通知所有参与者提交)。
- Spring支持:通过
JtaTransactionManager
整合JTA(Java Transaction API),适配支持JTA的容器(如JBoss)或分布式事务管理器(如Atomikos)。
@Bean public PlatformTransactionManager transactionManager() {return new JtaTransactionManager(); // 基于JTA的分布式事务管理器 }
-
2. TCC(Try-Confirm-Cancel)
- 原理:自定义三个阶段(尝试资源检查与预留、确认操作、取消操作),业务侵入性强但性能好。
- Spring支持:无原生支持,需结合中间件(如Seata)实现。
// TCC示例接口 public interface OrderTccService {void tryCreate(Order order); // 尝试创建订单(预留库存)void confirmCreate(Order order); // 确认创建void cancelCreate(Order order); // 取消创建(释放库存) }
-
3. SAGA模式
- 原理:将分布式事务拆分为本地事务序列,通过补偿事务回滚。
- Spring支持:可通过Spring StateMachine实现状态流转,或结合Seata、Hmily等框架。
-
4. 本地消息表
- 原理:通过本地事务记录消息,异步通知其他服务,最终一致性方案。
- Spring支持:结合Spring事务和消息队列(如RabbitMQ)实现。
-
Spring Cloud相关支持:
- Spring Cloud Alibaba Seata:提供AT(自动补偿)、TCC等模式的分布式事务支持。
- Spring Cloud Stream:结合消息队列实现最终一致性事务。
54. 请解释事务的ACID特性。
事务的ACID特性是保证数据一致性的四大核心原则:
-
原子性(Atomicity)
事务是不可分割的最小单元,要么全部执行成功,要么全部失败回滚,不存在部分执行的情况。
例如:转账操作中,“A账户扣款”和“B账户收款”必须同时成功或同时失败。 -
一致性(Consistency)
事务执行前后,数据从一个合法状态转换为另一个合法状态,满足业务规则约束。
例如:转账前后,A和B的账户总金额保持不变。 -
隔离性(Isolation)
多个并发事务之间相互隔离,一个事务的执行不应被其他事务干扰,避免并发问题(脏读、不可重复读、幻读)。
数据库通过锁机制和MVCC(多版本并发控制)实现隔离性。 -
持久性(Durability)
事务一旦提交,其修改会永久保存到数据库中,即使系统崩溃也不会丢失。
数据库通过日志(如redo log)实现持久性,确保提交的数据可恢复。
55. 什么是脏读、不可重复读、幻读?如何通过隔离级别避免?
-
脏读(Dirty Read)
一个事务读取到另一个未提交事务修改的数据。- 示例:事务A修改了数据但未提交,事务B读取到该数据,随后事务A回滚,事务B读取的数据为“脏数据”。
- 避免方式:隔离级别设为
READ_COMMITTED
及以上。
-
不可重复读(Non-Repeatable Read)
同一事务内,多次读取同一数据时,结果不一致(因其他事务修改并提交了该数据)。- 示例:事务A第一次读取数据为100,事务B修改数据为200并提交,事务A再次读取数据为200。
- 避免方式:隔离级别设为
REPEATABLE_READ
及以上。
-
幻读(Phantom Read)
同一事务内,多次执行相同查询时,结果集行数不一致(因其他事务插入或删除了数据)。- 示例:事务A查询年龄>20的用户有3人,事务B插入1个年龄>20的用户并提交,事务A再次查询发现有4人。
- 避免方式:隔离级别设为
SERIALIZABLE
(最高级别,通过全表锁避免幻读)。
-
隔离级别与并发问题的关系:
隔离级别 脏读 不可重复读 幻读 READ_UNCOMMITTED 可能 可能 可能 READ_COMMITTED 避免 可能 可能 REPEATABLE_READ 避免 避免 可能 SERIALIZABLE 避免 避免 避免
56. Spring事务管理中,如何指定事务的回滚规则?
Spring事务默认会对所有未检查异常(RuntimeException及其子类) 和Error进行回滚,对已检查异常(如IOException、SQLException等) 不回滚。若需自定义回滚规则,可通过以下方式实现:
原理说明:
- 通过
@Transactional
注解的rollbackFor
和noRollbackFor
属性指定回滚或不回滚的异常类型。 rollbackFor
:指定需要回滚的异常(即使是已检查异常)。noRollbackFor
:指定不需要回滚的异常(即使是未检查异常)。
示例代码:
@Service
public class UserService {// 对NullPointerException和IOException回滚,对ArithmeticException不回滚@Transactional(rollbackFor = {NullPointerException.class, IOException.class}, noRollbackFor = ArithmeticException.class)public void updateUser() throws IOException {// 业务逻辑if (true) {throw new IOException("IO异常,触发回滚");}if (true) {throw new ArithmeticException("算术异常,不回滚");}}
}
57. 只读事务的作用是什么?
只读事务是指事务执行过程中不修改数据,仅进行查询操作。其作用主要体现在性能优化和数据库约束上。
原理说明:
- 性能优化:数据库可针对只读事务进行优化(如避免加写锁、减少日志记录等),尤其在批量查询场景下提升效率。
- 约束提示:明确告知数据库和Spring该事务无写操作,数据库可能拒绝在只读事务中执行更新语句(如MySQL的InnoDB引擎)。
示例代码:
@Service
public class UserService {// 标记为只读事务@Transactional(readOnly = true)public List<User> queryAllUsers() {// 仅查询操作,无更新return userDao.findAll();}
}
注意:
- 若在只读事务中执行更新操作,可能抛出异常(如
SQLException: Connection is read-only
)。 - 只读事务仅对
REQUIRED
、REQUIRES_NEW
等传播行为有效。
58. 嵌套事务和事务传播行为中的NESTED有什么关系?
- 嵌套事务:是一种事务嵌套机制,外层事务中可以包含内层事务,内层事务依赖外层事务,外层事务回滚时内层事务也会回滚,但内层事务回滚不影响外层事务(除非手动设置)。
- NESTED传播行为:Spring通过
propagation = Propagation.NESTED
支持嵌套事务,其底层依赖数据库的保存点(Savepoint) 机制。
关系说明:
NESTED
是Spring实现嵌套事务的方式之一,外层事务会为内层事务创建保存点。- 内层事务回滚时,仅回滚到保存点,不影响外层事务的后续操作;外层事务回滚时,所有内层事务均回滚。
示例代码:
@Service
public class OrderService {@Autowiredprivate PaymentService paymentService;@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {// 外层事务逻辑(如创建订单)try {paymentService.pay(); // 调用内层NESTED事务} catch (Exception e) {// 内层事务回滚,外层事务可继续执行System.out.println("支付失败,订单仍可继续处理");}}
}@Service
public class PaymentService {// 内层嵌套事务@Transactional(propagation = Propagation.NESTED)public void pay() {// 支付逻辑,若失败则回滚到保存点throw new RuntimeException("支付失败");}
}
59. 如何在Spring中使用编程式事务?
编程式事务是通过手动编写代码控制事务的开始、提交和回滚,适用于需要细粒度控制事务的场景。Spring中可通过PlatformTransactionManager
和TransactionTemplate
实现。
原理说明:
PlatformTransactionManager
:事务管理器核心接口,定义了getTransaction()
(获取事务)、commit()
(提交)、rollback()
(回滚)方法。TransactionTemplate
:模板类,简化编程式事务代码,通过execute()
方法封装事务逻辑。
示例代码:
@Service
public class ProductService {@Autowiredprivate PlatformTransactionManager transactionManager;@Autowiredprivate ProductDao productDao;// 方式1:使用PlatformTransactionManager手动控制public void updateProduct1() {// 定义事务属性DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 获取事务状态TransactionStatus status = transactionManager.getTransaction(def);try {// 业务逻辑productDao.updateStock();transactionManager.commit(status); // 提交事务} catch (Exception e) {transactionManager.rollback(status); // 回滚事务throw e;}}// 方式2:使用TransactionTemplate(推荐)public void updateProduct2() {TransactionTemplate template = new TransactionTemplate(transactionManager);template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);template.execute(status -> {try {// 业务逻辑productDao.updateStock();return null;} catch (Exception e) {status.setRollbackOnly(); // 标记回滚throw e;}});}
}
60. Spring事务同步机制是什么?
Spring事务同步机制是指在事务生命周期的特定阶段(如提交后、回滚后) 执行自定义逻辑的机制,通过TransactionSynchronization
接口实现。
原理说明:
- 当事务启动后,可注册
TransactionSynchronization
实例到TransactionSynchronizationManager
中。 - 事务执行到不同阶段(如
beforeCommit
、afterCommit
、afterRollback
等)时,Spring会回调同步器的对应方法。
示例代码:
@Service
public class OrderService {@Transactionalpublic void createOrder() {// 注册事务同步器TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void beforeCommit(boolean readOnly) {System.out.println("事务提交前执行(如数据校验)");}@Overridepublic void afterCommit() {System.out.println("事务提交后执行(如发送消息通知)");}@Overridepublic void afterRollback() {System.out.println("事务回滚后执行(如日志记录)");}});// 业务逻辑:创建订单orderDao.insert();}
}
应用场景:
- 事务提交后发送消息、更新缓存。
- 事务回滚后记录审计日志。
61. @Transactional注解的 propagation=REQUIRES_NEW 和 NESTED 有什么区别?
特性 | REQUIRES_NEW | NESTED |
---|---|---|
事务独立性 | 开启全新事务,与外层事务完全独立 | 依赖外层事务,内层事务是外层的一部分 |
回滚影响 | 内层事务回滚不影响外层,外层回滚不影响内层 | 内层回滚不影响外层,外层回滚会带动内层回滚 |
底层实现 | 依赖事务管理器创建新事务 | 依赖数据库保存点(Savepoint) |
适用场景 | 日志记录、独立操作(如扣积分) | 嵌套业务(如订单创建包含支付) |
示例代码:
@Service
public class OrderService {@Autowiredprivate PaymentService paymentService;// 外层事务@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {System.out.println("创建订单");try {// 调用REQUIRES_NEW的内层事务paymentService.payWithRequiresNew();// 调用NESTED的内层事务paymentService.payWithNested();} catch (Exception e) {// 外层事务回滚时:// - REQUIRES_NEW的内层事务已独立提交,不受影响// - NESTED的内层事务会随外层回滚}}
}@Service
public class PaymentService {// REQUIRES_NEW:创建新事务@Transactional(propagation = Propagation.REQUIRES_NEW)public void payWithRequiresNew() {System.out.println("执行支付(REQUIRES_NEW)");}// NESTED:嵌套事务@Transactional(propagation = Propagation.NESTED)public void payWithNested() {System.out.println("执行支付(NESTED)");}
}
62. 为什么说事务的隔离级别越高,性能可能越低?
事务隔离级别定义了多个并发事务之间的可见性规则,隔离级别越高,数据一致性越强,但需要更多的锁机制或资源开销,导致性能下降。
原因分析:
- 读未提交(READ_UNCOMMITTED):几乎无锁,性能最高,但可能出现脏读。
- 读已提交(READ_COMMITTED):通过行级锁避免脏读,但需频繁加锁/解锁,性能中等。
- 可重复读(REPEATABLE_READ):通过间隙锁(如MySQL InnoDB)避免不可重复读和幻读,锁范围扩大,性能下降。
- 串行化(SERIALIZABLE):最高隔离级别,通过表级锁强制事务串行执行,并发能力极差,性能最低。
总结:
隔离级别升高 → 锁机制更复杂(锁范围更大、持有时间更长) → 并发冲突增加 → 性能降低。实际开发中需在一致性和性能间权衡(如多数场景使用READ_COMMITTED)。
63. 如何在Spring中实现事务的手动回滚?
Spring支持通过编程方式手动触发事务回滚,适用于需要根据业务逻辑判断是否回滚的场景。
实现方式:
-
通过
TransactionStatus
手动回滚(编程式事务):@Service public class UserService {@Autowiredprivate PlatformTransactionManager transactionManager;public void updateUser() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// 业务逻辑if (/* 满足回滚条件 */) {transactionManager.rollback(status); // 手动回滚return;}transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}} }
-
通过
TransactionAspectSupport
回滚(声明式事务):@Service public class UserService {@Transactionalpublic void updateUser() {try {// 业务逻辑if (/* 满足回滚条件 */) {// 手动触发回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();return;}} catch (Exception e) {// 自动回滚或手动增强TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}} }
64. 多线程环境下,Spring事务会出现什么问题?如何解决?
问题说明:
Spring事务基于线程绑定(通过ThreadLocal
实现),多线程环境下,子线程无法继承父线程的事务上下文,可能导致:
- 子线程的操作脱离父线程事务,无法一起提交或回滚。
- 事务资源(如数据库连接)在多线程间共享时出现并发问题。
解决方式:
- 避免在事务中开启子线程:将多线程逻辑移到事务外,通过分布式事务或消息队列保证一致性。
- 手动传递事务上下文(不推荐,复杂度高):
@Service public class OrderService {@Transactionalpublic void createOrder() {// 获取当前事务上下文TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();// 子线程中手动绑定上下文(需自定义事务管理器支持)new Thread(() -> {TransactionSynchronizationManager.bindResource(dataSource, status.getConnectionHolder());try {// 子线程业务逻辑} finally {TransactionSynchronizationManager.unbindResource(dataSource);}}).start();} }
- 使用分布式事务框架(如Seata):适用于跨服务多线程场景。
65. 什么是事务的超时时间?如何配置?
事务的超时时间是指事务从开始到提交的最大允许时间,若超过该时间未提交,事务会自动回滚,避免长期占用资源。
配置方式:
-
通过
@Transactional
注解的timeout
属性(单位:秒,默认-1表示不超时):@Service public class OrderService {// 事务超时时间设置为5秒@Transactional(timeout = 5)public void createOrder() {// 业务逻辑(若执行超过5秒,自动回滚)try {Thread.sleep(6000); // 模拟超时} catch (InterruptedException e) {e.printStackTrace();}} }
-
XML配置方式:
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="create*" timeout="5"/> <!-- 超时5秒 --></tx:attributes> </tx:advice>
注意:
- 超时时间从事务开始(获取数据库连接)到提交前的总时间,不包括提交过程本身。
- 底层依赖数据库支持(如MySQL的
innodb_lock_wait_timeout
可能影响实际超时行为)。