全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 8 分钟 ✍️ juanwangdev

Java事务管理与隔离级别

事务是数据库操作的基本单位,保证操作的原子性和一致性。

事务ACID特性

特性说明
Atomicity(原子性)事务要么全部成功,要么全部失败
Consistency(一致性)事务前后数据状态一致
Isolation(隔离性)事务之间互不干扰
Durability(持久性)事务提交后永久保存

JDBC事务管理

手动事务管理

Java
Connection conn = dataSource.getConnection();
try {
    conn.setAutoCommit(false);  // 关闭自动提交

    // 执行多个SQL
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
    stmt.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE id = 2");

    conn.commit();  // 提交事务

} catch (SQLException e) {
    conn.rollback();  // 回滚事务
    throw e;
} finally {
    conn.setAutoCommit(true);  // 恢复自动提交
    conn.close();
}

设置保存点

Java
Connection conn = dataSource.getConnection();
try {
    conn.setAutoCommit(false);

    Statement stmt = conn.createStatement();
    stmt.executeUpdate("INSERT INTO orders VALUES(1, 'order1')");

    Savepoint sp1 = conn.setSavepoint("sp1");  // 设置保存点

    stmt.executeUpdate("INSERT INTO orders VALUES(2, 'order2')");

    // 可回滚到保存点
    conn.rollback(sp1);  // 只回滚到sp1,保留第一条

    conn.commit();

} catch (SQLException e) {
    conn.rollback();
} finally {
    conn.close();
}

事务隔离级别

四种隔离级别

隔离级别脏读不可重复读幻读性能
READ_UNCOMMITTED可能可能可能最高
READ_COMMITTED不可能可能可能
REPEATABLE_READ不可能不可能可能
SERIALIZABLE不可能不可能不可能最低

并发问题详解

Java
脏读:读到其他事务未提交的数据
┌─────────┬──────────────────┐
│ 事务A   │ UPDATE balance=0 │
│         │ (未提交)          │
├─────────┼──────────────────┤
│ 事务B   │ SELECT balance   │
│         │ 读到0(脏读)     │
├─────────┼──────────────────┤
│ 事务A   │ ROLLBACK         │
│         │ balance恢复100   │
└─────────┴──────────────────┘

不可重复读:同一事务两次读取结果不同
┌─────────┬──────────────────┐
│ 事务A   │ SELECT balance=100│
├─────────┼──────────────────┤
│ 事务B   │ UPDATE balance=50 │
│         │ COMMIT           │
├─────────┼──────────────────┤
│ 事务A   │ SELECT balance=50 │
│         │ 前后不一致       │
└─────────┴──────────────────┘

幻读:同一事务两次查询记录数不同
┌─────────┬──────────────────┐
│ 事务A   │ SELECT COUNT=10  │
├─────────┼──────────────────┤
│ 事务B   │ INSERT 新记录    │
│         │ COMMIT           │
├─────────┼──────────────────┤
│ 事务A   │ SELECT COUNT=11  │
│         │ 多了一条(幻读) │
└─────────┴──────────────────┘

JDBC设置隔离级别

SQL
Connection conn = dataSource.getConnection();

// 设置隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

// 隔离级别常量
Connection.TRANSACTION_READ_UNCOMMITTED  // 读未提交
Connection.TRANSACTION_READ_COMMITTED    // 读已提交(MySQL默认)
Connection.TRANSACTION_REPEATABLE_READ   // 可重复读(MySQL InnoDB默认)
Connection.TRANSACTION_SERIALIZABLE      // 序列化

// 查看当前隔离级别
int level = conn.getTransactionIsolation();

MySQL隔离级别

Java
-- 查看隔离级别
SELECT @@transaction_isolation;

-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- InnoDB默认:REPEATABLE_READ
-- 且通过MVCC解决幻读,性能较好

Spring事务管理

@Transactional注解

Java
@Service
public class UserService {

    @Transactional
    public void transfer(int fromId, int toId, int amount) {
        accountDao.decreaseBalance(fromId, amount);
        accountDao.increaseBalance(toId, amount);
    }

    @Transactional(
        propagation = Propagation.REQUIRED,    // 传播行为
        isolation = Isolation.READ_COMMITTED,  // 隤离级别
        timeout = 30,                          // 超时秒数
        readOnly = false,                      // 只读
        rollbackFor = Exception.class          // 回滚异常
    )
    public void complexOperation() {
        // ...
    }
}

传播行为

传播行为说明
REQUIRED有事务则加入,无则新建(默认)
REQUIRES_NEW总是新建事务,挂起已有事务
SUPPORTS有事务则加入,无则非事务执行
NOT_SUPPORTED非事务执行,挂起已有事务
MANDATORY必须在事务中,否则抛异常
NEVER必须非事务执行,否则抛异常
NESTED有事务则嵌套执行
Java
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void independentTransaction() {
    // 独立事务,不受外部事务影响
}

@Transactional(propagation = Propagation.NESTED)
public void nestedTransaction() {
    // 嵌套事务,可独立回滚不影响外层
}

事务回滚规则

Java
@Transactional(rollbackFor = Exception.class)  // 所有异常回滚
@Transactional(rollbackFor = {SQLException.class, IOException.class})
@Transactional(noRollbackFor = BusinessException.class)  // 不回滚

// 默认:只对RuntimeException和Error回滚
// checked异常不回滚,需显式指定

编程式事务

Java
@Service
public class UserService {
    @Autowired
    private TransactionTemplate transactionTemplate;

    public void transfer(int fromId, int toId, int amount) {
        transactionTemplate.execute(status -> {
            accountDao.decreaseBalance(fromId, amount);
            accountDao.increaseBalance(toId, amount);
            return null;
        });
    }
}

分布式事务

问题场景

Java
服务A ───→ DB1 ───→ 扣款成功
服务B ───→ DB2 ───→ 加款失败

如何保证跨库事务一致性?

解决方案

方案特点
2PC/XA强一致性,性能差
TCC最终一致,需补偿代码
Seata阿里开源,支持多种模式
Saga长事务,编排补偿
本地消息表最终一致,简单可靠
Java
// Seata @GlobalTransactional
@GlobalTransactional
public void distributedTransfer(int fromId, int toId, int amount) {
    accountServiceA.decrease(fromId, amount);
    accountServiceB.increase(toId, amount);
}

事务最佳实践

1. 事务范围最小化

Java
// 不推荐:事务范围大
@Transactional
public void processOrder(Order order) {
    validateOrder(order);      // 校验(不需要事务)
    calculatePrice(order);     // 计算(不需要事务)
    saveOrder(order);          // 保存(需要事务)
    sendNotification(order);   // 发通知(不需要事务)
}

// 推荐:事务范围小
public void processOrder(Order order) {
    validateOrder(order);
    calculatePrice(order);
    saveOrderInTransaction(order);  // 只在这里开启事务
    sendNotification(order);
}

@Transactional
private void saveOrderInTransaction(Order order) {
    orderDao.save(order);
}

2. 避免长事务

text
// 不推荐:长事务
@Transactional
public void batchProcess(List<Item> items) {
    for (Item item : items) {
        processItem(item);  // 1000个处理,事务很长
    }
}

// 推荐:分批短事务
public void batchProcess(List<Item> items) {
    for (Item item : items) {
        processItemInTransaction(item);  // 每个独立事务
    }
}

3. 只读查询不加事务

text
// 不推荐:查询也加事务
@Transactional
public List<User> findAll() {
    return userDao.findAll();
}

// 推荐:只读不加事务,或只读事务
@Transactional(readOnly = true)
public List<User> findAll() {
    return userDao.findAll();
}

注意事项

事务方法必须是public

同类调用事务方法失效(绕过代理)

长事务占用连接,影响性能

只读事务可优化数据库行为

分布式事务需专门方案解决

要点总结

  1. 事务ACID:原子性、一致性、隔离性、持久性
  2. 四种隔离级别:读未提交、读已提交、可重复读、序列化
  3. Spring @Transactional管理事务,设置传播行为和隔离级别
  4. 事务范围应最小化,避免长事务
  5. 分布式事务使用Seata/TCC/Saga等方案

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java SQL注入防范
下一篇 → Java大数据量分页查询
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库