当前位置: 首页 > news >正文

Java并发编程之事务管理详解

关键词:Java 并发、事务管理、ACID、JDBC 事务、Spring 事务、多线程事务、分布式事务


✅ 摘要

在高并发系统中,事务的正确性和一致性是保障数据安全的关键。Java 提供了丰富的事务管理机制,包括 JDBC 原生事务控制、Spring 的声明式事务、以及基于 AOP 的事务增强 等方式。

本文将深入讲解 Java 中事务的核心概念、事务的 ACID 特性、事务的传播行为、事务失效场景、并发环境下的事务问题、Spring Boot 中的事务管理实践等内容,并提供大量 可运行的示例代码,帮助你全面掌握 Java 事务的使用方式与底层原理。


📌 一、什么是事务?

1.1 事务的基本定义

事务(Transaction)是一组数据库操作,这些操作要么全部成功执行,要么全部失败回滚,保证数据库状态的一致性。

1.2 事务的四大特性(ACID)

特性描述
A(Atomicity)原子性事务是一个不可分割的工作单位,事务中的操作要么都做,要么都不做
C(Consistency)一致性事务必须使数据库从一个一致性状态变换到另一个一致性状态
I(Isolation)隔离性多个用户并发访问数据库时,数据库为每一个用户开启事务,不能被其他事务的操作干扰
D(Durability)持久性事务一旦提交,对数据库的修改就是永久性的

📌 二、Java 中的事务实现方式

2.1 JDBC 原生事务控制

Connection conn = null;
try {conn = dataSource.getConnection();conn.setAutoCommit(false); // 关闭自动提交// 执行 SQL 操作PreparedStatement ps1 = conn.prepareStatement("UPDATE account SET balance = balance - 100 WHERE id = 1");ps1.executeUpdate();PreparedStatement ps2 = conn.prepareStatement("UPDATE account SET balance = balance + 100 WHERE id = 2");ps2.executeUpdate();conn.commit(); // 提交事务
} catch (SQLException e) {if (conn != null) {try {conn.rollback(); // 回滚事务} catch (SQLException ex) {ex.printStackTrace();}}e.printStackTrace();
} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}
}

📌 注意点

  • 默认情况下,JDBC 是自动提交模式(autoCommit = true)
  • 使用事务时需手动关闭自动提交,并显式调用 commit 或 rollback

2.2 Spring 事务管理

Spring 提供了声明式事务管理能力,开发者只需通过注解即可完成事务控制。

示例:
@Service
public class AccountService {@Autowiredprivate AccountMapper accountMapper;@Transactionalpublic void transfer(Long fromId, Long toId, BigDecimal amount) {accountMapper.deduct(fromId, amount);accountMapper.add(toId, amount);// 模拟异常,触发事务回滚if (amount.compareTo(BigDecimal.ZERO) > 0) {throw new RuntimeException("转账失败");}}
}

📌 说明

  • @Transactional 注解表示该方法需要事务管理
  • 如果方法中抛出未检查异常(如 RuntimeException),Spring 会自动回滚事务
  • 若抛出的是检查型异常(checked exception),默认不会回滚,除非指定 @Transactional(rollbackFor = Exception.class)

📌 三、Spring 事务的传播行为(Propagation)

Spring 支持多种事务传播行为,用于控制方法之间的事务边界。

传播行为含义
REQUIRED(默认)如果当前没有事务,则新建一个事务;如果已经存在事务,则加入该事务
REQUIRES_NEW总是新建事务,并挂起当前事务(如果有)
SUPPORTS当前有事务则加入,没有则以非事务方式执行
NOT_SUPPORTED以非事务方式执行,挂起当前事务
MANDATORY必须存在事务,否则抛异常
NEVER不能存在事务,否则抛异常
NESTED在嵌套事务内执行,外部事务可以提交或回滚,内部事务不影响外部事务
示例:
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {// ...methodB(); // methodB 也具有事务
}@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {// 即使 methodA 有事务,methodB 也会开启新事务
}

📌 四、事务失效的常见原因及解决方案

原因描述解决方案
自调用问题同一个类中,methodA() 调用 methodB(),而 methodB@Transactional 注解,但事务不生效使用 AopContext.currentProxy() 调用代理对象
异常被捕获未抛出方法中捕获了异常但未重新抛出,导致 Spring 无法感知异常发生抛出异常或手动设置回滚
方法不是 public@Transactional 只能作用于 public 方法修改为 public 方法
事务配置错误数据源未正确配置事务管理器检查 @EnableTransactionManagementPlatformTransactionManager 配置
非 Spring 管理的 Bean手动 new 出来的对象无法被 Spring 管理事务使用依赖注入获取 Bean

📌 五、并发环境下事务的问题

5.1 丢失更新(Lost Update)

两个事务同时更新同一记录,后提交的事务覆盖了前者的更改。

解决方案

  • 加锁(悲观锁/乐观锁)
  • 使用 @Version 实现乐观锁版本号机制

5.2 脏读(Dirty Read)

事务 A 读取到了事务 B 未提交的数据。

解决方案

  • 设置事务隔离级别为 READ COMMITTED

5.3 不可重复读(Non-Repeatable Read)

事务 A 在两次查询之间,事务 B 提交了更改,导致 A 查询结果不同。

解决方案

  • 设置事务隔离级别为 REPEATABLE READ

5.4 幻读(Phantom Read)

事务 A 在范围查询期间,事务 B 插入了新记录,导致 A 第二次查询出现“幻影”行。

解决方案

  • 设置事务隔离级别为 SERIALIZABLE 或使用间隙锁(Gap Lock)

📌 六、Spring Boot 中的事务配置

6.1 启用事务管理

@SpringBootApplication
@EnableTransactionManagement
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

6.2 自定义事务管理器(适用于多数据源)

@Configuration
public class TransactionConfig {@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

📌 七、多线程下的事务问题

在多线程环境中,每个线程拥有独立的事务上下文,事务无法跨线程传播。

7.1 问题示例

@Transactional
public void multiThreadOperation() {new Thread(() -> {// 此处的数据库操作不在事务中accountMapper.updateBalance(...);}).start();
}

7.2 解决方案

  • 将事务逻辑封装为异步任务,并由事务管理器统一调度
  • 使用 TransactionTemplate 编程式事务
  • 使用线程池配合 ThreadLocal 传递事务上下文(适用于复杂场景)

📌 八、分布式事务简介(简要)

在微服务架构下,多个服务之间操作同一个业务逻辑,就涉及分布式事务。

常见方案:

方案特点
2PC / XA 两阶段提交强一致性,性能差,资源锁定时间长
TCC 补偿事务最终一致性,开发成本高
Saga 模式事件驱动,适合长周期流程
Seata 分布式事务框架阿里开源,支持 AT 模式、TCC 模式等
消息队列 + 本地事务表适用于最终一致性场景

✅ 总结

模块内容
事务基础ACID 特性、JDBC 事务控制
Spring 事务@Transactional、传播行为、事务失效处理
事务并发问题丢失更新、脏读、不可重复读、幻读
Spring Boot 配置启用事务、多数据源事务管理
多线程事务事务上下文隔离、线程池整合建议
分布式事务2PC、TCC、Seata 简介

📚 参考资料

  • Spring Framework 官方文档 - Transaction Management
http://www.dtcms.com/a/279784.html

相关文章:

  • Redis集群方案——Redis分片集群
  • GPU集群运维
  • Unity物理系统由浅入深第六节:高级主题与前沿探索
  • 动态规划题解——乘积最大子数组【LeetCode】
  • 【EM算法】算法及注解
  • 12.4 Hinton与Jeff Dean突破之作:稀疏门控MoE如何用1%计算量训练万亿参数模型?
  • 【python】基于pygame实现动态粒子爱心
  • Qualcomm FastConnect C7700:新一代Wi-Fi 7
  • Js 压缩图片为 120 kb且使用canvas显示(一键运行)
  • 【EM算法】三硬币模型
  • [硬件电路-21]:模拟信号处理运算与数字信号处理运算的详细比较
  • 连分数的收敛判别与计算方法
  • 鸿蒙开发NDK之---- 如何将ArkTs的类型转化成C++对应的类型(基础类型,包含部分代码解释)
  • Jetson平台CSI摄像头采集与显示:gst-launch-1.0与OpenCV实战
  • 【linux V0.11】boot
  • 多生产者多消费者问题(操作系统os)
  • SpringCloud之Hystrix
  • 【DOCKER】-4 dockerfile镜像管理
  • linux网络存储——freeNAS的安装配置
  • Spring Cloud分布式配置中心:架构设计与技术实践
  • MFC/C++语言怎么比较CString类型 第一个字符
  • 读文章 Critiques of World model
  • Java(集合)
  • aspnetcore Mvc配置选项中的ModelMetadataDetailsProviders
  • SAP-ABAP:SAP库存管理核心增强:IF_EX_MB_DOCUMENT_BADI 深度解析
  • 交换类排序的C语言实现
  • Hello, Tauri!
  • 基于Android的景点旅游信息系统App
  • 使用aiohttp实现高并发爬虫
  • uni-app开发的页面跳转全局加载中