事务处理与并发控制:ACID vs BASE 理论与实践


文档摘要

事务处理与并发控制:ACID vs BASE 理论与实践 事务基础 ACID 特性 A(Atomicity)原子性: C(Consistency)一致性: I(Isolation)隔离性: java -- 隔离级别 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 隔离级别 读未提交(Read Uncommitted) 读已提交(Read Committed) 可重复读(Repeatable Read) 串行化(Serializable) 并发控制 悲锁 乐观锁: 悲观锁: 死锁检测 分布式事务 2PC(两阶段提交) Saga 模式 性能优化 连接池配置 批处理 只读事务优化 最佳实践 事务边界 避免长事务 故障排查 死锁排查 长事务识别 总结

事务处理与并发控制:ACID vs BASE 理论与实践

事务基础

ACID 特性

A(Atomicity)原子性

BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; COMMIT; -- 两个更新要么都成功,要么都失败

C(Consistency)一致性

-- 一致性约束 ALTER TABLE users ADD CONSTRAINT email_unique UNIQUE (email);

I(Isolation)隔离性
``java
-- 隔离级别
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

**D(Durability)持久性**: ``java -- 提交后数据永久保存 COMMIT;

隔离级别

1. 读未提交(Read Uncommitted)

-- 可能读到未提交的数据 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

2. 读已提交(Read Committed)

-- 只能读已提交的数据 SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

3. 可重复读(Repeatable Read)

-- 同一事务中多次读取结果一致 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

4. 串行化(Serializable)

-- 完全串行化,最严格 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

并发控制

1. 悲锁

乐观锁

@Entity public class Product { @Version private Long version; @OptimisticLocking @Transactional public void updatePrice(Long id, BigDecimal newPrice) { Product product = productRepository.findById(id).orElseThrow(); int oldVersion = product.getVersion(); product.setPrice(newPrice); int updated = productRepository.update(product); if (updated == 0) { throw new OptimisticLockingFailureException("数据已被修改"); } } }

悲观锁

@Lock("product") @Transactional public void updateStock(Long productId, int quantity) { Product product = productRepository.findById(productId) .orElseThrow(); product.setStock(product.getStock() - quantity); productRepository.save(product); }

2. 死锁检测

@Entity public class Order { @Id private Long id; private String orderNo; @Version private Long version; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Order order = (Order) o; return id != null && id.equals(order.id); } }

分布式事务

1. 2PC(两阶段提交)

@GlobalTransactional public void transferMoney(String fromAccount, String toAccount, BigDecimal amount) { // 阶段 1:准备阶段 accountDao.debit(fromAccount, amount); accountDao.credit(toAccount, amount); // 阶段 2:提交阶段(Seata 自动处理) // 如果失败,Seata 自动回滚 }

2. Saga 模式

@SagaOrchestrationStart(name = "orderFulfillmentSaga") public class OrderFulfillmentSaga { @SagaStep(completionMethod = "cancelInventory") public void reserveInventory(Order order) { inventoryService.reserve(order.getProductId(), order.getQuantity()); } @SagaStep(completionMethod = "refundPayment") public void processPayment(Order order) { paymentService.charge(order.getUserId(), order.getAmount()); } @SagaStep(completionMethod = "cancelOrder") public void completeOrder(Order order) { orderService.markAsCompleted(order.getId()); } }

性能优化

1. 连接池配置

spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 idle-timeout: 300000 max-lifetime: 1200000 connection-timeout: 30000

2. 批处理

@Transactional public void batchInsert(List<User> users) { int batchSize = 1000; for (int i = 0; i < users.size(); i += batchSize) { int end = Math.min(i + batchSize, users.size()); List<User> batch = users.subList(i, end); userRepository.saveAll(batch); // 刷新并清空缓存 entityManager.flush(); entityManager.clear(); } }

3. 只读事务优化

@Transactional(readOnly = true) public List<Order> getOrdersByStatus(String status) { return orderRepository.findByStatus(status); }

最佳实践

1. 事务边界

// ❌ 不好的做法:事务过大 @Transactional public void processOrder() { // 查询用户 // 创建订单 // 更新库存 // 扣款 // 发货 // 评价 // ... 太多逻辑 } // ✅ 好的做法:小事务 @Transactional public void createOrder(Order order) { orderRepository.save(order); } @Transactional public void deductInventory(Order order) { inventoryService.deduct(order); } @Transactional public void processPayment(Order order) { paymentService.charge(order); }

2. 避免长事务

// ❌ 不好的做法 @Transactional(timeout = 60) public void longRunningTask() { // 耗时的同步操作 processLargeDataset(); } // ✅ 好的做法 @Async public CompletableFuture<Void> longRunningTaskAsync() { return CompletableFuture.runAsync(() -> { processLargeDataset(); return null; }); }

故障排查

1. 死锁排查

-- 查看死锁 SELECT l.lock_type, l.lock_mode, l.lock_table, l.lock_id, trx.trx_id, trx.trx_mysql_thread_id, FROM information_schema.innodb_lock_waits w JOIN information_schema.innodb_trx trx ON w.trx_id = trx.trx_id JOIN information_schema.innodb_locks l ON l.lock_id = w.lock_id WHERE w.lock_wait_time > 5;

2. 长事务识别

-- 查看长时间运行的事务 SELECT trx.trx_id, trx.trx_started, TIMESTAMPDIFF(SECOND, trx.trx_started) AS duration_s FROM information_schema.innodb_trx trx WHERE trx.trx_state = 'ACTIVE' ORDER BY duration_s DESC;

总结

事务和并发控制要点:

  1. ACID 特性:理解隔离级别的权衡
  2. 锁策略:乐观锁 vs 悲观锁
  3. 分布式事务:2PC vs Saga
  4. 性能优化:连接池、批处理、只读优化
  5. 最佳实践:小事务、避免长事务

掌握事务,保证数据一致性!


发布者: 作者: 转发
评论区 (0)
U