html特效网站,能够做二维码网站,网站建设平台设备,书店网站模板下载一、事务的本质#xff1a;数据库操作的原子性保证
想象你正在银行进行转账操作#xff1a;
-- 从A账户扣除1000元
UPDATE accounts SET balance balance - 1000 WHERE id A;-- 向B账户增加1000元
UPDATE accounts SET balance balance 1000 WHERE id B;关…一、事务的本质数据库操作的原子性保证
想象你正在银行进行转账操作
-- 从A账户扣除1000元
UPDATE accounts SET balance balance - 1000 WHERE id A;-- 向B账户增加1000元
UPDATE accounts SET balance balance 1000 WHERE id B;关键问题如果第一条SQL执行后系统崩溃会发生什么
A账户被扣款但B账户未收到 → 数据不一致
事务解决方案
START TRANSACTION; -- 开启事务UPDATE accounts SET balance balance - 1000 WHERE id A;
UPDATE accounts SET balance balance 1000 WHERE id B;COMMIT; -- 提交事务或ROLLBACK回滚事务确保要么所有操作都成功要么全部失败回滚
二、Spring事务核心概念
1. 事务四大特性ACID
特性说明示例Atomicity原子性事务是不可分割的最小单元转账操作要么全执行要么全不执行Consistency一致性事务前后数据状态一致转账前后总金额不变Isolation隔离性并发事务互不干扰转账时其他查询不受影响Durability持久性事务提交后永久生效转账成功后数据永久保存
2. Spring事务管理关键接口 public interface PlatformTransactionManager {// 获取事务状态TransactionStatus getTransaction(TransactionDefinition definition);// 提交事务void commit(TransactionStatus status);// 回滚事务void rollback(TransactionStatus status);
}public interface TransactionDefinition {// 传播行为int getPropagationBehavior();// 隔离级别int getIsolationLevel();// 超时时间int getTimeout();// 是否只读boolean isReadOnly();
}三、事务传播机制详解
1. 为什么需要传播机制
考虑电商下单场景
Service
public class OrderService {Transactionalpublic void createOrder(Order order) {// 保存订单orderDao.save(order);// 扣减库存inventoryService.deductStock(order);// 增加积分pointsService.addPoints(order.getUserId(), order.getAmount());}
}Service
public class InventoryService {Transactionalpublic void deductStock(Order order) {// 扣减库存逻辑}
}关键问题
当createOrder调用deductStock时应该使用同一个事务还是独立事务如果库存扣减失败订单是否应该回滚传播机制定义了事务方法相互调用时的行为规则
2. 七种传播行为详解
(1) REQUIRED默认有则加入无则新建
Transactional(propagation Propagation.REQUIRED)
public void methodA() {// 事务操作...methodB(); // 调用B方法
}Transactional(propagation Propagation.REQUIRED)
public void methodB() {// 事务操作...
}行为分析
如果methodA有事务methodB加入该事务如果methodA无事务methodB新建事务
适用场景大多数业务场景如订单创建流程
2) SUPPORTS有则加入无则非事务
Transactional(propagation Propagation.SUPPORTS)
public void getProductInfo(Long id) {// 查询操作
}行为分析
调用方有事务加入事务调用方无事务非事务执行
适用场景查询操作可读性优先
(3) MANDATORY必须有事务否则抛异常
Transactional(propagation Propagation.MANDATORY)
public void updatePrice(Product product) {// 更新价格
}适用场景必须保证事务性的操作如资金变动
(4) REQUIRES_NEW新建独立事务
Transactional(propagation Propagation.REQUIRES_NEW)
public void logOperation(String action) {// 记录操作日志
}行为分析
无论调用方是否有事务都新建事务挂起调用方事务如果存在
适用场景日志记录、非核心操作失败不影响主流程
(5) NOT_SUPPORTED非事务执行
Transactional(propagation Propagation.NOT_SUPPORTED)
public void sendNotification(User user) {// 发送通知无需事务
}行为分析
挂起调用方事务如果存在非事务执行当前方法
适用场景发送消息、通知等非关键操作
(6) NEVER禁止事务否则抛异常
Transactional(propagation Propagation.NEVER)
public void getCacheData(String key) {// 获取缓存数据
}行为分析
调用方有事务抛出IllegalTransactionStateException调用方无事务正常执行
适用场景缓存操作等不需要事务的场景
(7) NESTED嵌套事务
Transactional(propagation Propagation.NESTED)
public void updateInventory(Order order) {// 更新库存
}行为分析
调用方有事务创建嵌套事务保存点调用方无事务新建事务同REQUIRED
特点
嵌套事务回滚不影响外部事务外部事务回滚会导致嵌套事务回滚
适用场景部分可独立失败的操作如库存扣减
3. 传播行为对比表
传播行为当前有事务当前无事务异常影响范围适用场景REQUIRED加入新建全部回滚通用业务SUPPORTS加入非事务部分回滚查询操作MANDATORY加入抛异常全部回滚关键操作REQUIRES_NEW新建新建独立回滚日志记录NOT_SUPPORTED非事务非事务无影响通知发送NEVER抛异常非事务无影响缓存操作NESTED嵌套事务新建部分回滚库存扣减
四、传播机制实战案例
案例1订单创建REQUIRED REQUIRES_NEW
Service
public class OrderService {Autowiredprivate OrderDao orderDao;Autowiredprivate LogService logService;Transactional(propagation Propagation.REQUIRED)public void createOrder(Order order) {try {// 保存订单orderDao.save(order);// 记录日志独立事务logService.log(订单创建, order.getId());} catch (Exception e) {// 订单保存失败会回滚但日志已独立提交throw new OrderException(订单创建失败);}}
}Service
public class LogService {Transactional(propagation Propagation.REQUIRES_NEW)public void log(String action, Long orderId) {// 记录操作日志即使订单失败日志仍保留}
}案例2用户注册NESTED事务
Service
public class UserService {Transactional(propagation Propagation.REQUIRED)public void register(User user) {// 保存用户userDao.save(user);try {// 初始化账户嵌套事务accountService.initAccount(user.getId());} catch (Exception e) {// 账户初始化失败但用户注册仍成功log.error(账户初始化失败, e);}// 发送欢迎邮件非事务emailService.sendWelcomeEmail(user.getEmail());}
}Service
public class AccountService {Transactional(propagation Propagation.NESTED)public void initAccount(Long userId) {// 初始化用户账户可独立失败}
}五、隔离级别与传播机制协同
1. 隔离级别回顾
隔离级别脏读不可重复读幻读性能READ_UNCOMMITTED✓✓✓高READ_COMMITTED✗✓✓中REPEATABLE_READ✗✗✓中低SERIALIZABLE✗✗✗低
2. 隔离级别与传播行为组合
// 资金转账服务高隔离级别
Transactional(propagation Propagation.REQUIRED,isolation Isolation.REPEATABLE_READ
)
public void transfer(TransferRequest request) {// 转账核心逻辑
}// 商品查询服务低隔离级别
Transactional(propagation Propagation.SUPPORTS,isolation Isolation.READ_COMMITTED
)
public Product getProduct(Long id) {// 查询商品信息
}六、Spring事务实现原理
传播行为实现关键代码
public class TransactionManager {public void execute(TransactionDefinition definition, Runnable task) {// 1. 获取当前事务状态TransactionStatus status getTransaction(definition);try {// 2. 执行业务逻辑task.run();// 3. 提交事务commit(status);} catch (Exception ex) {// 4. 回滚事务rollback(status);throw ex;}}private TransactionStatus getTransaction(TransactionDefinition definition) {// 传播行为处理switch (definition.getPropagationBehavior()) {case REQUIRED:if (currentTransactionExists()) {return handleExistingTransaction(definition);}return startNewTransaction(definition);case REQUIRES_NEW:suspendCurrentTransaction();return startNewTransaction(definition);case NESTED:if (currentTransactionExists()) {return createNestedTransaction();}return startNewTransaction(definition);// 其他传播行为...}}
}七、常见问题与解决方案
1. 事务不生效的常见原因
问题原因解决方案方法非public改为public方法自调用问题通过AopContext获取代理异常类型错误配置rollbackFor数据库引擎不支持使用InnoDB引擎多数据源未指定明确指定事务管理器
2. 自调用问题解决方案
Service
public class UserService {// 注入自身代理Autowired private UserService selfProxy;public void batchUpdate() {for (User user : users) {// 通过代理调用保证事务生效selfProxy.updateUser(user);}}Transactionalpublic void updateUser(User user) {// 更新用户}
}3. 正确配置回滚异常
// 默认只回滚RuntimeException
Transactional(rollbackFor Exception.class)
public void updateData() throws BusinessException {// 可能抛出受检异常
}八、性能优化建议
1. 事务优化策略
策略实现方式效果缩短事务时间事务内避免远程调用减少锁竞争降低隔离级别使用READ_COMMITTED提高并发使用只读事务Transactional(readOnlytrue)MySQL优化合理设置超时Transactional(timeout30)防止死锁
2. 批量操作优化
Transactional
public void batchInsert(ListUser users) {for (int i 0; i users.size(); i) {userDao.insert(users.get(i));// 每100条提交一次if (i % 100 0) {entityManager.flush();entityManager.clear();}}
}九、最佳实践总结
1. 事务设计原则
原则说明示例最小事务原则事务范围尽量小避免在事务中处理业务逻辑明确传播行为显式指定传播类型Transactional(propagationPropagation.REQUIRED)合理设置隔离级别根据业务需求选择查询操作使用READ_COMMITTED异常处理一致统一异常回滚策略配置rollbackFor 2. 事务使用清单
// 1. 在Service层使用事务
Service
public class OrderService {// 2. 显式指定传播行为Transactional(propagation Propagation.REQUIRED)public void createOrder(Order order) {// 3. 避免在事务中进行远程调用orderDao.save(order);// 4. 非核心操作使用REQUIRES_NEWlogService.logOrderCreation(order.getId());}// 5. 查询方法使用只读事务Transactional(readOnly true)public Order getOrder(Long id) {return orderDao.findById(id);}
}总结事务传播的本质
Spring事务传播机制的核心是解决事务边界问题它定义了
事务从哪里开始创建新事务事务到哪里结束提交/回滚事务之间的关系加入/独立
通过合理使用传播行为我们可以
保证数据一致性提高系统性能增强代码可维护性灵活处理复杂业务场景
根据业务需求选择最合适的传播行为而不是盲目使用默认值。