事务(Transaction)详解

事务(Transaction)详解

1. 什么是事务?

事务(Transaction)是数据库操作的最小工作单元,保证多个 SQL 语句作为一个整体执行,要么全部成功,要么全部失败,确保数据的一致性和完整性。

例如,在银行转账的场景中:

  1. 从 A 账户扣除 100 元
  2. 向 B 账户增加 100 元

如果第一步执行成功,但第二步失败(比如数据库崩溃),账户 A 的钱就凭空少了,这会导致数据不一致事务可以保证这两个操作要么都成功,要么都回滚(撤销),避免数据错误。


2. 事务的 4 大特性(ACID)

事务具有 ACID 这四个关键特性:

特性含义
A(Atomicity)原子性事务中的操作不可分割,要么全部成功,要么全部失败
C(Consistency)一致性事务执行前后,数据必须保持一致(符合业务规则)
I(Isolation)隔离性并发事务之间相互隔离,避免影响
D(Durability)持久性事务提交后,数据永久保存,即使系统崩溃

3. 事务隔离级别

当多个事务同时运行时,可能会出现脏读、不可重复读、幻读等问题。数据库提供了不同的隔离级别来控制事务之间的影响。

隔离级别脏读不可重复读幻读性能
读未提交(Read Uncommitted)可能可能可能高(并发高)
读已提交(Read Committed)不可能可能可能
可重复读(Repeatable Read)(MySQL 默认)不可能不可能可能
串行化(Serializable)不可能不可能不可能最低(锁表)

问题解释:

  • 脏读:一个事务可以读取另一个未提交事务的数据(导致错误)。
  • 不可重复读:同一事务中多次读取同一条记录,结果不一致(因为别的事务修改了数据)。
  • 幻读:事务 A 读取了一批符合条件的记录,但事务 B 插入了新记录,事务 A 重新查询时发现数据变了。

4. Spring 事务管理

Spring 提供了声明式事务编程式事务两种方式来管理事务。

4.1 声明式事务(推荐)

Spring 通过 @Transactional 注解 实现事务管理,无需手动编写 commit()rollback()

示例:转账操作

@Service
public class AccountService {

    @Autowired
    private AccountDao accountDao;

    @Transactional // 开启事务
    public void transferMoney(int fromId, int toId, double amount) {
        accountDao.decreaseBalance(fromId, amount);  // 扣款
        accountDao.increaseBalance(toId, amount);  // 加款
    }
}

🚀 如果 increaseBalance() 失败,Spring 会自动回滚 decreaseBalance(),保证事务完整性!


4.2 事务的传播机制

当一个事务调用另一个事务方法时,Spring 提供了7 种事务传播机制,决定新事务如何运行:

传播行为作用
REQUIRED(默认)如果当前没有事务,就创建新事务;否则加入已有事务
REQUIRES_NEW总是创建新事务,挂起当前事务
SUPPORTS支持当前事务,如果没有就不开启事务
MANDATORY必须在已有事务中运行,否则抛异常
NOT_SUPPORTED不支持事务,在非事务环境下运行
NEVER不能在事务中运行,否则抛异常
NESTED在当前事务中创建子事务,可独立回滚

示例:REQUIRES_NEW 让子方法独立事务执行

@Transactional
public void mainTransaction() {
    saveOrder();  // 事务 1
    saveLog();    // 事务 2
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog() {
    // 这个方法的事务与 mainTransaction() 独立
}

🚀 如果 saveOrder() 失败,saveLog() 依然会提交!


5. 编程式事务

如果你需要手动控制事务提交/回滚,可以使用 TransactionTemplatePlatformTransactionManager

@Autowired
private PlatformTransactionManager transactionManager;

public void updateData() {
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    TransactionStatus status = transactionManager.getTransaction(def);
    
    try {
        // 执行业务逻辑
        transactionManager.commit(status);
    } catch (Exception e) {
        transactionManager.rollback(status);  // 出错回滚
    }
}

🚀 适用于需要灵活控制事务提交/回滚的场景!


6. 事务的回滚

默认情况下,Spring 只会对运行时异常(RuntimeException)回滚,而不会回滚 CheckedException(受检异常)。

如果你希望 所有异常都回滚,可以使用 rollbackFor

@Transactional(rollbackFor = Exception.class)
public void processTransaction() {
    // 任何异常都会回滚
}

7. 数据库事务 VS Spring 事务

特性数据库事务Spring 事务
适用范围仅限数据库支持数据库、消息队列、缓存等
事务传播由数据库控制Spring 提供 7 种传播机制
编程方式手动 commit()/rollback()声明式 @Transactional

8. 总结

  • 事务保证数据一致性,避免数据丢失、不一致问题
  • ACID 特性确保事务的可靠性。
  • Spring 事务管理支持 声明式(推荐)编程式 两种方式。
  • 事务传播机制控制事务如何在不同方法间传播。
  • 事务隔离级别影响并发事务的行为,MySQL 默认"可重复读"(Repeatable Read)
  • 默认情况下,Spring 只对 RuntimeException 进行回滚CheckedException 不回滚。

Spring 事务管理非常强大,可以帮助我们轻松实现高并发环境下的数据安全,在企业级开发中至关重要!🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值