架构之事务性数据存储

架构之事务性数据存储

引言

在数字化时代,数据已经成为企业最重要的资产之一。而对于需要事务性保证的数据操作,如何确保数据的完整性、一致性和可靠性,成为架构设计的核心挑战。事务性数据存储架构法则强调:对于需要原子性、一致性、隔离性、持久性(ACID)事务保证的数据操作场景,使用关系型数据库管理系统(RDBMS)/SQL数据库,通过完善的事务机制确保数据的完整性和业务的一致性

事务性数据操作是业务系统的核心命脉。金融交易、订单处理、库存管理、账户系统等关键业务都依赖于强事务保证。一旦数据一致性出现问题,不仅会导致业务损失,更可能引发严重的信任危机。

事务性数据存储的核心理念

为什么需要事务性保证?

数据一致性挑战
业务复杂性
并发访问冲突
系统故障风险
数据完整性要求
合规性需求
多表关联更新
业务流程复杂
状态转换严格
回滚机制复杂
脏读问题
不可重复读
幻读现象
丢失更新
硬件故障
网络中断
软件崩溃
断电事故
主键约束
外键约束
唯一性约束
检查约束
金融监管
审计要求
数据追溯
合规报告

事务性保证能够有效解决上述挑战:

  • 原子性保证:确保操作要么全部成功,要么全部失败,避免数据不一致状态
  • 一致性维护:通过约束和规则保证数据始终处于有效状态
  • 隔离性保护:防止并发操作相互干扰,确保数据正确性
  • 持久性承诺:一旦事务提交,数据永久保存,不受系统故障影响

ACID特性详解

ACID特性
原子性 Atomicity
一致性 Consistency
隔离性 Isolation
持久性 Durability
全有或全无
事务回滚
undo日志
自动恢复
业务规则
数据约束
状态验证
完整性检查
并发控制
锁机制
MVCC
隔离级别
持久化存储
redo日志
崩溃恢复
WAL机制

事务性数据存储架构设计原则

1. 强一致性原则

确保数据在任何时刻都保持一致状态,不允许出现中间状态或不一致情况。

// 强一致性事务实现
@Service
public class TransactionalBankingService {
    
    @Autowired
    private AccountRepository accountRepository;
    
    @Autowired
    private TransactionRepository transactionRepository;
    
    /**
     * 银行转账:强一致性要求
     */
    @Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED)
    public TransferResult transferMoney(TransferRequest request) {
        log.info("开始转账事务: from={}, to={}, amount={}", 
            request.getFromAccount(), request.getToAccount(), request.getAmount());
        
        try {
            // 1. 获取账户信息(加锁)
            Account fromAccount = accountRepository.findByAccountNumberForUpdate(request.getFromAccount());
            Account toAccount = accountRepository.findByAccountNumberForUpdate(request.getToAccount());
            
            // 2. 验证账户状态
            validateAccountStatus(fromAccount, toAccount);
            
            // 3. 检查余额充足性
            if (fromAccount.getBalance().compareTo(request.getAmount()) < 0) {
                throw new InsufficientBalanceException("账户余额不足");
            }
            
            // 4. 执行转账操作
            // 4.1 扣减源账户余额
            BigDecimal newFromBalance = fromAccount.getBalance().subtract(request.getAmount());
            fromAccount.setBalance(newFromBalance);
            accountRepository.update(fromAccount);
            
            // 4.2 增加目标账户余额
            BigDecimal newToBalance = toAccount.getBalance().add(request.getAmount());
            toAccount.setBalance(newToBalance);
            accountRepository.update(toAccount);
            
            // 5. 记录交易明细
            TransactionRecord transaction = TransactionRecord.builder()
                .transactionId(generateTransactionId())
                .fromAccount(request.getFromAccount())
                .toAccount(request.getToAccount())
                .amount(request.getAmount())
                .transactionType(TransactionType.TRANSFER)
                .status(TransactionStatus.COMPLETED)
                .createTime(LocalDateTime.now())
                .build();
            transactionRepository.save(transaction);
            
            // 6. 记录账户变动历史
            recordAccountHistory(fromAccount, request.getAmount(), TransactionType.DEBIT);
            recordAccountHistory(toAccount, request.getAmount(), TransactionType.CREDIT);
            
            log.info("转账事务成功: transactionId={}", transaction.getTransactionId());
            
            return TransferResult.success(transaction.getTransactionId());
            
        } catch (Exception e) {
            log.error("转账事务失败", e);
            throw new TransactionException("转账操作失败", e);
        }
    }
    
    /**
     * 验证账户状态
     */
    private void validateAccountStatus(Account fromAccount, Account toAccount) {
        // 检查账户是否存在
        if (fromAccount == null || toAccount == null) {
            throw new AccountNotFoundException("账户不存在");
        }
        
        // 检查账户状态
        if (fromAccount.getStatus() != AccountStatus.ACTIVE) {
            throw new AccountInactiveException("源账户状态异常");
        }
        
        if (toAccount.getStatus() != AccountStatus.ACTIVE) {
            throw new AccountInactiveException("目标账户状态异常");
        }
        
        // 检查账户类型是否支持转账
        if (!isTransferAllowed(fromAccount.getAccountType(), toAccount.getAccountType())) {
            throw new InvalidAccountTypeException("账户类型不支持转账");
        }
    }
}

2. 隔离级别选择原则

根据业务场景选择合适的隔离级别,平衡一致性和性能。

// 隔离级别选择策略
@Component
public class IsolationLevelSelector {
    
    /**
     * 根据业务场景选择隔离级别
     */
    public IsolationLevel selectIsolationLevel(BusinessScenario scenario) {
        switch (scenario.getType()) {
            case BANKING_TRANSFER:
                // 银行转账:最高隔离级别,防止任何并发问题
                return IsolationLevel.SERIALIZABLE;
                
            case INVENTORY_MANAGEMENT:
                // 库存管理:防止幻读,确保库存准确性
                return IsolationLevel.REPEATABLE_READ;
                
            case USER_REGISTRATION:
                // 用户注册:防止不可重复读,确保用户名唯一性
                return IsolationLevel.READ_COMMITTED;
                
            case REPORT_GENERATION:
                // 报表生成:允许读取已提交数据,提高并发性
                return IsolationLevel.READ_COMMITTED;
                
            case LOG_RECORDING:
                // 日志记录:允许读取未提交数据,追求最高性能
                return IsolationLevel.READ_UNCOMMITTED;
                
            default:
                // 默认使用READ_COMMITTED
                return IsolationLevel.READ_COMMITTED;
        }
    }
}

// 不同隔离级别的实现示例
@Repository
public class IsolationLevelDemoRepository {
    
    /**
     * READ_UNCOMMITTED:读取未提交数据
     * 适用场景:对数据一致性要求不高,追求极致性能
     */
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public List<LogEntry> getRecentLogs() {
        // 可以读取其他事务未提交的数据
        return jdbcTemplate.query(
            "SELECT * FROM system_logs ORDER BY create_time DESC LIMIT 100",
            new LogEntryRowMapper()
        );
    }
    
    /**
     * READ_COMMITTED:读取已提交数据(大多数数据库的默认级别)
     * 适用场景:一般业务查询,防止脏读
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public UserProfile getUserProfile(Long userId) {
        // 只能读取已提交的数据,防止脏读
        return jdbcTemplate.queryForObject(
            "SELECT * FROM user_profiles WHERE user_id = ?",
            new Object[]{userId},
            new UserProfileRowMapper()
        );
    }
    
    /**
     * REPEATABLE_READ:可重复读
     * 适用场景:需要多次读取同一数据,确保数据一致性
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public OrderStatistics calculateOrderStatistics(Long userId) {
        // 在同一个事务中,多次读取同一数据结果一致
        BigDecimal totalAmount = jdbcTemplate.queryForObject(
            "SELECT SUM(amount) FROM orders WHERE user_id = ?",
            new Object[]{userId},
            BigDecimal.class
        );
        
        Integer orderCount = jdbcTemplate.queryForObject(
            "SELECT COUNT(*) FROM orders WHERE user_id = ?",
            new Object[]{userId},
            Integer.class
        );
        
        return OrderStatistics.builder()
            .userId(userId)
            .totalAmount(totalAmount != null ? totalAmount : BigDecimal.ZERO)
            .orderCount(orderCount != null ? orderCount : 0)
            .build();
    }
    
    /**
     * SERIALIZABLE:串行化
     * 适用场景:金融交易,需要最高级别的数据一致性
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public boolean transferInventory(Long productId, Integer quantity, String fromWarehouse, String toWarehouse) {
        // 完全串行化执行,防止所有并发问题
        // 1. 检查源仓库库存
        Integer fromStock = jdbcTemplate.queryForObject(
            "SELECT stock_quantity FROM warehouse_inventory WHERE product_id = ? AND warehouse_code = ? FOR UPDATE",
            new Object[]{productId, fromWarehouse},
            Integer.class
        );
        
        if (fromStock == null || fromStock < quantity) {
            throw new InsufficientInventoryException("源仓库库存不足");
        }
        
        // 2. 扣减源仓库库存
        jdbcTemplate.update(
            "UPDATE warehouse_inventory SET stock_quantity = stock_quantity - ? WHERE product_id = ? AND warehouse_code = ?",
            quantity, productId, fromWarehouse
        );
        
        // 3. 增加目标仓库库存
        Integer updatedRows = jdbcTemplate.update(
            "UPDATE warehouse_inventory SET stock_quantity = stock_quantity + ? WHERE product_id = ? AND warehouse_code = ?",
            quantity, productId, toWarehouse
        );
        
        // 4. 如果目标仓库没有该商品,插入新记录
        if (updatedRows == 0) {
            jdbcTemplate.update(
                "INSERT INTO warehouse_inventory (product_id, warehouse_code, stock_quantity) VALUES (?, ?, ?)",
                productId, toWarehouse, quantity
            );
        }
        
        // 5. 记录库存移动历史
        recordInventoryMovement(productId, quantity, fromWarehouse, toWarehouse);
        
        return true;
    }
}

3. 异常处理原则

建立完善的异常处理机制,确保事务的正确回滚和数据的一致性。

// 事务异常处理机制
@Service
public class TransactionalExceptionHandler {
    
    private static final Logger log = LoggerFactory.getLogger(TransactionalExceptionHandler.class);
    
    /**
     * 订单处理:完整的事务异常处理示例
     */
    @Transactional(rollbackFor = {BusinessException.class, SystemException.class})
    public OrderProcessingResult processOrder(OrderRequest request) {
        String orderId = null;
        OrderStatus originalStatus = null;
        
        try {
            // 1. 创建订单
            Order order = createOrder(request);
            orderId = order.getOrderId();
            log.info("订单创建成功: orderId={}", orderId);
            
            // 2. 扣减库存
            deductInventory(order);
            log.info("库存扣减成功: orderId={}", orderId);
            
            // 3. 计算价格
            calculatePrice(order);
            log.info("价格计算成功: orderId={}", orderId);
            
            // 4. 应用促销
            applyPromotion(order);
            log.info("促销应用成功: orderId={}", orderId);
            
            // 5. 更新订单状态
            originalStatus = order.getStatus();
            updateOrderStatus(order, OrderStatus.PROCESSING);
            log.info("订单状态更新成功: orderId={}", orderId);
            
            // 6. 发送通知
            sendOrderNotification(order);
            log.info("通知发送成功: orderId={}", orderId);
            
            return OrderProcessingResult.success(orderId);
            
        } catch (BusinessException e) {
            // 业务异常:记录日志,事务会自动回滚
            log.error("订单处理业务异常: orderId={}, error={}", orderId, e.getMessage());
            throw e; // 重新抛出,触发事务回滚
            
        } catch (DataAccessException e) {
            // 数据访问异常:可能是数据库连接问题
            log.error("数据访问异常: orderId={}", orderId, e);
            throw new SystemException("数据库操作失败", e);
            
        } catch (Exception e) {
            // 未知异常:记录详细信息
            log.error("订单处理未知异常: orderId={}", orderId, e);
            throw new SystemException("系统处理异常", e);
            
        } finally {
            // 清理资源:关闭连接、释放锁等
            cleanupResources(orderId);
        }
    }
    
    /**
     * 库存扣减:特定的异常处理策略
     */
    private void deductInventory(Order order) {
        try {
            inventoryService.deductInventory(order.getItems());
            
        } catch (InsufficientInventoryException e) {
            // 库存不足:业务异常,需要回滚
            log.warn("库存不足: orderId={}, productId={}, required={}, available={}", 
                order.getOrderId(), e.getProductId(), e.getRequiredQuantity(), e.getAvailableQuantity());
            throw new BusinessException("商品库存不足", e);
            
        } catch (InventoryLockException e) {
            // 库存锁定失败:可能是并发冲突
            log.error("库存锁定失败: orderId={}", order.getOrderId(), e);
            throw new BusinessException("商品正在被其他用户购买,请稍后重试", e);
            
        } catch (Exception e) {
            // 其他库存相关异常
            log.error("库存扣减异常: orderId={}", order.getOrderId(), e);
            throw new SystemException("库存系统异常", e);
        }
    }
    
    /**
     * 价格计算:处理复杂的业务异常
     */
    private void calculatePrice(Order order) {
        try {
            priceService.calculateOrderPrice(order);
            
        } catch (PriceExpiredException e) {
            // 价格已过期:需要重新获取最新价格
            log.warn("价格已过期: orderId={}, productId={}", order.getOrderId(), e.getProductId());
            
            // 尝试重新获取价格
            boolean priceUpdated = priceService.refreshProductPrice(e.getProductId());
            if (priceUpdated) {
                // 价格更新成功,重新计算
                priceService.calculateOrderPrice(order);
            } else {
                throw new BusinessException("商品价格已变动,请重新下单", e);
            }
            
        } catch (PromotionExpiredException e) {
            // 促销已过期:移除促销重新计算
            log.warn("促销已过期: orderId={}, promotionId={}", order.getOrderId(), e.getPromotionId());
            
            // 移除过期促销
            order.removePromotion(e.getPromotionId());
            
            // 重新计算价格
            priceService.calculateOrderPrice(order);
            
        } catch (Exception e) {
            log.error("价格计算异常: orderId={}", order.getOrderId(), e);
            throw new SystemException("价格计算失败", e);
        }
    }
    
    /**
     * 事务补偿机制
     */
    public void compensateFailedOrder(String orderId, OrderStatus originalStatus) {
        log.info("开始订单补偿: orderId={}, originalStatus={}", orderId, originalStatus);
        
        try {
            Order order = orderRepository.findByOrderId(orderId);
            if (order == null) {
                log.warn("订单不存在,无法补偿: orderId={}", orderId);
                return;
            }
            
            // 1. 恢复库存
            if (order.getInventoryDeducted()) {
                inventoryService.restoreInventory(order.getItems());
                log.info("库存恢复成功: orderId={}", orderId);
            }
            
            // 2. 恢复优惠券
            if (order.getCouponsUsed() != null && !order.getCouponsUsed().isEmpty()) {
                couponService.restoreCoupons(order.getUserId(), order.getCouponsUsed());
                log.info("优惠券恢复成功: orderId={}", orderId);
            }
            
            // 3. 恢复积分
            if (order.getPointsDeducted() > 0) {
                pointService.restorePoints(order.getUserId(), order.getPointsDeducted());
                log.info("积分恢复成功: orderId={}", orderId);
            }
            
            // 4. 更新订单状态
            order.setStatus(OrderStatus.CANCELLED);
            order.setCancelTime(LocalDateTime.now());
            order.setCancelReason("系统异常,自动取消");
            orderRepository.update(order);
            
            log.info("订单补偿完成: orderId={}", orderId);
            
        } catch (Exception e) {
            log.error("订单补偿失败: orderId={}", orderId, e);
            // 发送告警,需要人工干预
            alertService.sendCompensationFailureAlert(orderId, e.getMessage());
        }
    }
}

事务性数据存储核心技术

1. 并发控制机制

通过锁机制和多版本并发控制(MVCC)确保事务的隔离性。

// 并发控制实现
@Component
public class ConcurrencyControlService {
    
    @Autowired
    private LockManager lockManager;
    
    /**
     * 悲观锁:适用于高冲突场景
     */
    @Transactional
    public boolean deductInventoryWithPessimisticLock(Long productId, Integer quantity) {
        // 使用SELECT FOR UPDATE加锁
        ProductInventory inventory = inventoryRepository.findByProductIdForUpdate(productId);
        
        if (inventory.getAvailableQuantity() < quantity) {
            return false;
        }
        
        // 扣减库存
        inventory.setAvailableQuantity(inventory.getAvailableQuantity() - quantity);
        inventoryRepository.update(inventory);
        
        return true;
    }
    
    /**
     * 乐观锁:适用于低冲突场景
     */
    @Transactional
    public boolean updateUserProfileWithOptimisticLock(UserProfile profile) {
        // 获取当前版本号
        UserProfile currentProfile = userProfileRepository.findByUserId(profile.getUserId());
        Integer currentVersion = currentProfile.getVersion();
        
        // 更新时检查版本号
        int updatedRows = userProfileRepository.updateWithVersion(profile, currentVersion);
        
        if (updatedRows == 0) {
            // 版本号不匹配,说明数据已被其他事务修改
            throw new OptimisticLockingFailureException("数据已被其他用户修改,请刷新后重试");
        }
        
        return true;
    }
    
    /**
     * 分布式锁:跨服务并发控制
     */
    public boolean processOrderWithDistributedLock(String orderId) {
        String lockKey = "order_processing:" + orderId;
        String lockValue = UUID.randomUUID().toString();
        
        try {
            // 获取分布式锁,超时时间30秒
            boolean locked = distributedLock.tryLock(lockKey, lockValue, 30, TimeUnit.SECONDS);
            
            if (!locked) {
                log.warn("获取分布式锁失败: orderId={}", orderId);
                return false;
            }
            
            // 处理订单
            return processOrder(orderId);
            
        } finally {
            // 释放分布式锁
            distributedLock.unlock(lockKey, lockValue);
        }
    }
    
    /**
     * MVCC读取:非阻塞读操作
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public AccountStatement generateAccountStatement(Long accountId, LocalDate startDate, LocalDate endDate) {
        // MVCC允许非阻塞读取,不会阻塞其他事务的写操作
        List<TransactionRecord> transactions = transactionRepository.findByAccountIdAndDateRange(
            accountId, startDate, endDate
        );
        
        // 计算期初余额(使用快照读)
        BigDecimal openingBalance = accountRepository.getBalanceAtDate(accountId, startDate.minusDays(1));
        
        // 计算期末余额
        BigDecimal closingBalance = openingBalance.add(
            transactions.stream()
                .map(TransactionRecord::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
        );
        
        return AccountStatement.builder()
            .accountId(accountId)
            .startDate(startDate)
            .endDate(endDate)
            .openingBalance(openingBalance)
            .closingBalance(closingBalance)
            .transactions(transactions)
            .build();
    }
}

2. 分布式事务处理

在微服务架构下处理跨服务的事务一致性。

// 分布式事务实现
@Service
public class DistributedTransactionService {
    
    @Autowired
    private SagaTransactionManager sagaManager;
    
    @Autowired
    private TccTransactionManager tccManager;
    
    /**
     * Saga模式:适用于长事务
     */
    public SagaTransaction createOrderSaga(CreateOrderRequest request) {
        SagaTransaction saga = SagaTransaction.builder()
            .transactionId(generateTransactionId())
            .transactionType("ORDER_CREATION")
            .status(SagaStatus.STARTED)
            .build();
        
        // 定义Saga步骤
        saga.addStep(SagaStep.builder()
            .stepName("CREATE_ORDER")
            .serviceName("order-service")
            .actionMethod("createOrder")
            .compensateMethod("cancelOrder")
            .build());
        
        saga.addStep(SagaStep.builder()
            .stepName("DEDUCT_INVENTORY")
            .serviceName("inventory-service")
            .actionMethod("deductInventory")
            .compensateMethod("restoreInventory")
            .build());
        
        saga.addStep(SagaStep.builder()
            .stepName("PROCESS_PAYMENT")
            .serviceName("payment-service")
            .actionMethod("processPayment")
            .compensateMethod("refundPayment")
            .build());
        
        // 执行Saga事务
        return sagaManager.executeSaga(saga, request);
    }
    
    /**
     * TCC模式:Try-Confirm-Cancel
     */
    public TccTransaction processOrderTcc(CreateOrderRequest request) {
        String transactionId = generateTransactionId();
        
        try {
            // Phase 1: Try阶段
            TccTransaction tcc = TccTransaction.builder()
                .transactionId(transactionId)
                .status(TccStatus.TRYING)
                .build();
            
            // Try:预留资源
            boolean tryResult = executeTryPhase(tcc, request);
            if (!tryResult) {
                throw new TccException("Try阶段失败");
            }
            
            // Phase 2: Confirm阶段
            tcc.setStatus(TccStatus.CONFIRMING);
            boolean confirmResult = executeConfirmPhase(tcc);
            if (!confirmResult) {
                throw new TccException("Confirm阶段失败");
            }
            
            tcc.setStatus(TccStatus.CONFIRMED);
            return tcc;
            
        } catch (Exception e) {
            log.error("TCC事务失败,开始Cancel阶段: transactionId={}", transactionId, e);
            
            // 执行Cancel阶段
            try {
                executeCancelPhase(transactionId);
            } catch (Exception cancelException) {
                log.error("Cancel阶段也失败: transactionId={}", transactionId, cancelException);
                // 发送告警,需要人工处理
                alertService.sendManualInterventionAlert(transactionId);
            }
            
            throw new TransactionException("订单处理失败", e);
        }
    }
    
    /**
     * 最大努力通知:适用于最终一致性要求
     */
    public void processOrderWithBestEffort(CreateOrderRequest request) {
        String orderId = generateOrderId();
        
        try {
            // 1. 本地事务:创建订单
            Order order = createOrderInLocalTransaction(request, orderId);
            
            // 2. 发送消息到消息队列
            OrderCreatedEvent event = OrderCreatedEvent.builder()
                .orderId(orderId)
                .userId(request.getUserId())
                .items(request.getItems())
                .totalAmount(order.getTotalAmount())
                .build();
            
            messageQueueService.sendOrderCreatedEvent(event);
            
            // 3. 等待下游服务处理
            // 下游服务通过消息队列异步处理库存扣减、支付等操作
            
            log.info("订单创建成功,等待下游处理: orderId={}", orderId);
            
        } catch (Exception e) {
            log.error("订单创建失败: orderId={}", orderId, e);
            throw new OrderCreationException("订单创建失败", e);
        }
    }
    
    /**
     * 可靠消息最终一致性
     */
    @Transactional
    public void processOrderWithReliableMessage(CreateOrderRequest request) {
        String orderId = generateOrderId();
        
        try {
            // 1. 准备消息
            OrderCreatedEvent event = OrderCreatedEvent.builder()
                .orderId(orderId)
                .userId(request.getUserId())
                .items(request.getItems())
                .build();
            
            // 2. 本地事务:创建订单 + 存储消息
            Order order = transactionTemplate.execute(status -> {
                // 创建订单
                Order newOrder = createOrder(request, orderId);
                
                // 存储消息到本地消息表
                OutboxMessage message = OutboxMessage.builder()
                    .messageId(generateMessageId())
                    .aggregateId(orderId)
                    .eventType("OrderCreated")
                    .payload(objectMapper.writeValueAsString(event))
                    .status(MessageStatus.PENDING)
                    .createTime(LocalDateTime.now())
                    .build();
                
                outboxMessageRepository.save(message);
                
                return newOrder;
            });
            
            // 3. 异步发送消息
            messageRelayService.relayMessages();
            
            log.info("可靠消息事务成功: orderId={}", orderId);
            
        } catch (Exception e) {
            log.error("可靠消息事务失败: orderId={}", orderId, e);
            throw new TransactionException("订单处理失败", e);
        }
    }
}

3. 事务监控与诊断

建立完善的事务监控体系,及时发现和解决事务相关问题。

// 事务监控服务
@Component
public class TransactionMonitorService {
    
    private static final Logger log = LoggerFactory.getLogger(TransactionMonitorService.class);
    
    @Autowired
    private MetricsCollector metricsCollector;
    
    @Autowired
    private AlertService alertService;
    
    /**
     * 事务性能监控
     */
    @EventListener
    public void handleTransactionCompletion(TransactionCompletionEvent event) {
        TransactionInfo txInfo = event.getTransactionInfo();
        
        // 记录事务执行时间
        long duration = txInfo.getCompletionTime() - txInfo.getStartTime();
        metricsCollector.recordTransactionDuration(txInfo.getTransactionType(), duration);
        
        // 记录事务结果
        if (txInfo.isSuccessful()) {
            metricsCollector.incrementTransactionSuccess(txInfo.getTransactionType());
        } else {
            metricsCollector.incrementTransactionFailure(txInfo.getTransactionType());
            log.warn("事务失败: transactionId={}, type={}, error={}", 
                txInfo.getTransactionId(), txInfo.getTransactionType(), txInfo.getErrorMessage());
        }
        
        // 慢事务告警
        if (duration > getSlowTransactionThreshold(txInfo.getTransactionType())) {
            alertService.sendSlowTransactionAlert(txInfo, duration);
        }
    }
    
    /**
     * 死锁检测与处理
     */
    @Scheduled(fixedDelay = 60000) // 每分钟检查一次
    public void detectDeadlocks() {
        try {
            List<DeadlockInfo> deadlocks = databaseAdminService.detectDeadlocks();
            
            for (DeadlockInfo deadlock : deadlocks) {
                log.error("检测到死锁: victim={}, participants={}", 
                    deadlock.getVictimTransaction(), deadlock.getParticipantTransactions());
                
                // 记录死锁信息
                metricsCollector.incrementDeadlockCount();
                
                // 发送死锁告警
                alertService.sendDeadlockAlert(deadlock);
                
                // 分析死锁原因
                analyzeDeadlockCause(deadlock);
            }
            
        } catch (Exception e) {
            log.error("死锁检测失败", e);
        }
    }
    
    /**
     * 事务超时监控
     */
    @Scheduled(fixedDelay = 30000) // 每30秒检查一次
    public void monitorTransactionTimeouts() {
        try {
            List<TransactionInfo> activeTransactions = transactionManager.getActiveTransactions();
            long currentTime = System.currentTimeMillis();
            
            for (TransactionInfo tx : activeTransactions) {
                long duration = currentTime - tx.getStartTime();
                
                // 检查是否超时
                if (duration > getTransactionTimeout(tx.getTransactionType())) {
                    log.warn("发现超时事务: transactionId={}, duration={}ms, type={}", 
                        tx.getTransactionId(), duration, tx.getTransactionType());
                    
                    // 强制回滚超时事务
                    try {
                        transactionManager.rollbackTransaction(tx.getTransactionId());
                        log.info("超时事务已回滚: transactionId={}", tx.getTransactionId());
                    } catch (Exception e) {
                        log.error("回滚超时事务失败: transactionId={}", tx.getTransactionId(), e);
                        alertService.sendTransactionRollbackFailureAlert(tx.getTransactionId(), e.getMessage());
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("事务超时监控失败", e);
        }
    }
    
    /**
     * 连接池监控
     */
    @Scheduled(fixedDelay = 10000) // 每10秒检查一次
    public void monitorConnectionPool() {
        try {
            ConnectionPoolMetrics metrics = dataSource.getConnectionPoolMetrics();
            
            // 检查连接池使用率
            double usageRate = (double) metrics.getActiveConnections() / metrics.getMaxConnections();
            if (usageRate > 0.9) {
                log.warn("连接池使用率过高: usageRate={}, active={}, max={}", 
                    usageRate, metrics.getActiveConnections(), metrics.getMaxConnections());
                alertService.sendConnectionPoolHighUsageAlert(metrics);
            }
            
            // 检查等待队列长度
            if (metrics.getWaitingConnections() > 50) {
                log.warn("连接池等待队列过长: waiting={}", metrics.getWaitingConnections());
                alertService.sendConnectionPoolQueueOverflowAlert(metrics);
            }
            
            // 记录连接池指标
            metricsCollector.recordConnectionPoolMetrics(metrics);
            
        } catch (Exception e) {
            log.error("连接池监控失败", e);
        }
    }
    
    /**
     * 长事务检测
     */
    @Scheduled(fixedDelay = 120000) // 每2分钟检查一次
    public void detectLongRunningTransactions() {
        try {
            List<TransactionInfo> longRunningTxs = transactionManager.getLongRunningTransactions(
                getLongTransactionThreshold()
            );
            
            for (TransactionInfo tx : longRunningTxs) {
                log.warn("发现长事务: transactionId={}, duration={}ms, type={}, sql={}", 
                    tx.getTransactionId(), 
                    System.currentTimeMillis() - tx.getStartTime(),
                    tx.getTransactionType(),
                    tx.getCurrentSql()
                );
                
                // 发送长事务告警
                alertService.sendLongRunningTransactionAlert(tx);
                
                // 记录长事务信息
                metricsCollector.recordLongRunningTransaction(tx);
            }
            
        } catch (Exception e) {
            log.error("长事务检测失败", e);
        }
    }
}

事务性数据存储最佳实践

1. 事务设计最佳实践

// 事务设计模式
@Component
public class TransactionDesignPatterns {
    
    /**
     * 模式1:事务脚本模式
     * 适用场景:简单业务逻辑
     */
    @Transactional
    public void transferMoneyScript(Long fromAccountId, Long toAccountId, BigDecimal amount) {
        // 1. 验证参数
        validateTransferParameters(fromAccountId, toAccountId, amount);
        
        // 2. 获取账户信息
        Account fromAccount = accountRepository.findById(fromAccountId);
        Account toAccount = accountRepository.findById(toAccountId);
        
        // 3. 业务验证
        validateAccounts(fromAccount, toAccount, amount);
        
        // 4. 执行转账
        performTransfer(fromAccount, toAccount, amount);
        
        // 5. 记录日志
        recordTransferLog(fromAccountId, toAccountId, amount);
    }
    
    /**
     * 模式2:领域模型模式
     * 适用场景:复杂业务逻辑
     */
    @Transactional
    public void processOrderDomainModel(OrderRequest request) {
        // 1. 加载聚合根
        Order order = orderRepository.findById(request.getOrderId());
        
        // 2. 执行业务操作(在领域对象内部处理业务规则)
        order.process(request);
        
        // 3. 保存聚合根(自动保存所有变更)
        orderRepository.save(order);
        
        // 4. 发布领域事件
        domainEventPublisher.publish(order.getDomainEvents());
    }
    
    /**
     * 模式3:工作单元模式
     * 适用场景:需要批量处理的场景
     */
    @Transactional
    public void batchProcessOrders(List<OrderRequest> requests) {
        // 创建工作单元
        UnitOfWork unitOfWork = unitOfWorkFactory.create();
        
        try {
            for (OrderRequest request : requests) {
                // 处理每个订单
                Order order = processSingleOrder(request);
                
                // 注册到工作单元
                unitOfWork.registerNew(order);
                
                // 批量处理,避免内存溢出
                if (unitOfWork.getChangeCount() >= BATCH_SIZE) {
                    unitOfWork.commit();
                    unitOfWork.clear();
                }
            }
            
            // 提交剩余变更
            if (unitOfWork.hasChanges()) {
                unitOfWork.commit();
            }
            
        } catch (Exception e) {
            // 回滚所有变更
            unitOfWork.rollback();
            throw new BatchProcessingException("批量处理失败", e);
        }
    }
    
    /**
     * 模式4:乐观离线锁模式
     * 适用场景:长事务、Web应用
     */
    @Transactional
    public void updateUserProfileWithOptimisticLock(UserProfileRequest request, Integer version) {
        // 1. 验证版本号
        UserProfile currentProfile = userProfileRepository.findByUserId(request.getUserId());
        
        if (!currentProfile.getVersion().equals(version)) {
            throw new OptimisticLockingException(
                String.format("数据已被其他用户修改,当前版本:%d,请求版本:%d", 
                    currentProfile.getVersion(), version)
            );
        }
        
        // 2. 更新数据
        currentProfile.update(request);
        
        // 3. 保存并自动增加版本号
        userProfileRepository.update(currentProfile);
        
        log.info("用户资料更新成功: userId={}, newVersion={}", 
            request.getUserId(), currentProfile.getVersion());
    }
}

2. 性能优化策略

# 数据库性能优化配置
performance_optimization:
  # 连接池优化
  connection_pool:
    hikari:
      maximum_pool_size: 50              # 最大连接数
      minimum_idle: 10                   # 最小空闲连接
      connection_timeout: 30000          # 连接超时时间
      idle_timeout: 600000               # 空闲超时时间
      max_lifetime: 1800000              # 最大生命周期
      leak_detection_threshold: 60000    # 泄露检测阈值
      
  # 事务超时设置
  transaction_timeout:
    default: 30                          # 默认事务超时(秒)
    long_running: 300                    # 长事务超时(秒)
    batch_processing: 600                # 批处理超时(秒)
    
  # 数据库优化
  database:
    mysql:
      innodb_buffer_pool_size: "8G"      # InnoDB缓冲池大小
      innodb_log_file_size: "2G"         # InnoDB日志文件大小
      innodb_flush_log_at_trx_commit: 2  # 事务提交刷新策略
      innodb_lock_wait_timeout: 50       # 锁等待超时时间
      transaction_isolation: "READ-COMMITTED"  # 事务隔离级别
      
  # 读写分离配置
  read_write_splitting:
    master:
      url: "jdbc:mysql://master-db:3306/myapp"
      username: "root"
      password: "password"
      driver_class_name: "com.mysql.cj.jdbc.Driver"
      
    slaves:
      - url: "jdbc:mysql://slave1-db:3306/myapp"
        username: "root"
        password: "password"
      - url: "jdbc:mysql://slave2-db:3306/myapp"
        username: "root"
        password: "password"
        
  # 分库分表配置
  sharding:
    databases:
      - name: "db0"
        url: "jdbc:mysql://db0-host:3306/myapp"
      - name: "db1"
        url: "jdbc:mysql://db1-host:3306/myapp"
        
    tables:
      user:
        actual_data_nodes: "db${0..1}.user_${0..3}"
        database_strategy:
          type: "INLINE"
          props:
            algorithm_expression: "db${user_id % 2}"
        table_strategy:
          type: "INLINE"
          props:
            algorithm_expression: "user_${user_id % 4}"

3. 监控告警配置

# Prometheus事务监控配置
groups:
- name: transaction_monitoring
  rules:
  
  # 事务失败率告警
  - alert: TransactionFailureRateHigh
    expr: rate(transaction_failures_total[5m]) / rate(transaction_total[5m]) > 0.05
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "事务失败率过高"
      description: "事务失败率 {{ $value | humanizePercentage }}"
  
  # 事务超时告警
  - alert: TransactionTimeoutHigh
    expr: rate(transaction_timeouts_total[5m]) > 10
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "事务超时数量过高"
      description: "事务超时数 {{ $value }}/秒"
  
  # 死锁告警
  - alert: DatabaseDeadlockDetected
    expr: increase(mysql_global_status_innodb_deadlocks[1m]) > 0
    for: 0m
    labels:
      severity: warning
    annotations:
      summary: "检测到数据库死锁"
      description: "InnoDB死锁数量 {{ $value }}"
  
  # 长事务告警
  - alert: LongRunningTransaction
    expr: mysql_info_schema_innodb_trx_trx_duration_seconds > 300
    for: 1m
    labels:
      severity: warning
    annotations:
      summary: "发现长事务"
      description: "事务运行时间 {{ $value }}秒"
  
  # 锁等待告警
  - alert: DatabaseLockWaitHigh
    expr: mysql_global_status_innodb_row_lock_waits > 100
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "数据库锁等待数量过高"
      description: "InnoDB行锁等待数 {{ $value }}"
  
  # 连接池使用率告警
  - alert: ConnectionPoolUsageHigh
    expr: hikaricp_connections_active / hikaricp_connections_max > 0.9
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "连接池使用率过高"
      description: "HikariCP连接池使用率 {{ $value | humanizePercentage }}"
  
  # 事务响应时间告警
  - alert: TransactionResponseTimeHigh
    expr: histogram_quantile(0.95, rate(transaction_duration_seconds_bucket[5m])) > 5
    for: 3m
    labels:
      severity: warning
    annotations:
      summary: "事务响应时间过长"
      description: "事务95分位响应时间 {{ $value }}秒"

事务性数据存储实践案例

1. 银行核心系统事务设计

// 银行核心系统事务处理
@Service
public class CoreBankingTransactionService {
    
    private static final Logger log = LoggerFactory.getLogger(CoreBankingTransactionService.class);
    
    @Autowired
    private AccountRepository accountRepository;
    
    @Autowired
    private TransactionRepository transactionRepository;
    
    @Autowired
    private AuditRepository auditRepository;
    
    /**
     * 核心转账业务:最高级别的事务保证
     */
    @Transactional(
        isolation = Isolation.SERIALIZABLE,
        propagation = Propagation.REQUIRED,
        timeout = 30,
        rollbackFor = {BankingException.class, SystemException.class}
    )
    public BankingTransactionResult processCoreTransfer(TransferRequest request) {
        String transactionId = generateTransactionId();
        log.info("开始核心转账事务: transactionId={}, from={}, to={}, amount={}", 
            transactionId, request.getFromAccount(), request.getToAccount(), request.getAmount());
        
        try {
            // 1. 参数验证
            validateTransferRequest(request);
            
            // 2. 账户锁定(防止并发)
            Account fromAccount = accountRepository.lockAccount(request.getFromAccount());
            Account toAccount = accountRepository.lockAccount(request.getToAccount());
            
            // 3. 账户状态检查
            validateAccountForTransfer(fromAccount, toAccount);
            
            // 4. 余额检查
            if (fromAccount.getAvailableBalance().compareTo(request.getAmount()) < 0) {
                throw new InsufficientBalanceException(
                    String.format("账户余额不足: account=%s, balance=%s, required=%s",
                        fromAccount.getAccountNumber(), fromAccount.getAvailableBalance(), request.getAmount())
                );
            }
            
            // 5. 执行转账
            // 5.1 扣减源账户
            BigDecimal newFromBalance = fromAccount.getAvailableBalance().subtract(request.getAmount());
            fromAccount.setAvailableBalance(newFromBalance);
            fromAccount.setLastTransactionTime(LocalDateTime.now());
            accountRepository.update(fromAccount);
            
            // 5.2 增加目标账户
            BigDecimal newToBalance = toAccount.getAvailableBalance().add(request.getAmount());
            toAccount.setAvailableBalance(newToBalance);
            toAccount.setLastTransactionTime(LocalDateTime.now());
            accountRepository.update(toAccount);
            
            // 6. 记录交易明细
            BankingTransaction bankingTx = BankingTransaction.builder()
                .transactionId(transactionId)
                .transactionType(TransactionType.TRANSFER)
                .fromAccount(request.getFromAccount())
                .toAccount(request.getToAccount())
                .amount(request.getAmount())
                .currency(request.getCurrency())
                .status(TransactionStatus.COMPLETED)
                .description(request.getDescription())
                .createTime(LocalDateTime.now())
                .build();
            transactionRepository.save(bankingTx);
            
            // 7. 记录账户流水
            recordAccountEntry(fromAccount, request.getAmount().negate(), transactionId, "转账支出");
            recordAccountEntry(toAccount, request.getAmount(), transactionId, "转账收入");
            
            // 8. 审计记录
            recordAuditLog(bankingTx, "核心转账完成");
            
            // 9. 风险监控
            riskMonitorService.monitorTransaction(bankingTx);
            
            log.info("核心转账事务成功: transactionId={}", transactionId);
            
            return BankingTransactionResult.success(transactionId);
            
        } catch (BankingException e) {
            log.error("银行业务异常: transactionId={}, error={}", transactionId, e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("核心转账系统异常: transactionId={}", transactionId, e);
            throw new SystemException("系统处理异常", e);
        }
    }
    
    /**
     * 批量转账处理
     */
    @Transactional
    public BatchTransferResult processBatchTransfer(BatchTransferRequest request) {
        log.info("开始批量转账: batchId={}, count={}", request.getBatchId(), request.getTransfers().size());
        
        List<TransferResult> results = new ArrayList<>();
        int successCount = 0;
        int failureCount = 0;
        
        try {
            // 1. 验证批量转账权限
            validateBatchTransferPermission(request);
            
            // 2. 预检查所有账户
            preValidateAccounts(request);
            
            // 3. 处理每笔转账
            for (TransferRequest transfer : request.getTransfers()) {
                try {
                    TransferResult result = processSingleTransfer(transfer);
                    results.add(result);
                    
                    if (result.isSuccess()) {
                        successCount++;
                    } else {
                        failureCount++;
                    }
                    
                } catch (Exception e) {
                    log.error("单笔转账失败: transfer={}", transfer, e);
                    results.add(TransferResult.failed(transfer.getRequestId(), e.getMessage()));
                    failureCount++;
                }
            }
            
            // 4. 记录批量转账结果
            BatchTransferRecord batchRecord = BatchTransferRecord.builder()
                .batchId(request.getBatchId())
                .totalCount(request.getTransfers().size())
                .successCount(successCount)
                .failureCount(failureCount)
                .totalAmount(calculateTotalAmount(request.getTransfers()))
                .status(failureCount == 0 ? BatchStatus.ALL_SUCCESS : 
                       successCount == 0 ? BatchStatus.ALL_FAILED : BatchStatus.PARTIAL_SUCCESS)
                .createTime(LocalDateTime.now())
                .build();
            
            batchTransferRepository.save(batchRecord);
            
            log.info("批量转账完成: batchId={}, success={}, failure={}", 
                request.getBatchId(), successCount, failureCount);
            
            return BatchTransferResult.builder()
                .batchId(request.getBatchId())
                .results(results)
                .successCount(successCount)
                .failureCount(failureCount)
                .status(batchRecord.getStatus())
                .build();
                
        } catch (Exception e) {
            log.error("批量转账异常: batchId={}", request.getBatchId(), e);
            throw new BatchTransferException("批量转账处理失败", e);
        }
    }
    
    /**
     * 事务补偿机制
     */
    @EventListener
    public void handleTransactionCompensation(TransactionCompensationEvent event) {
        log.info("开始事务补偿: transactionId={}, reason={}", 
            event.getTransactionId(), event.getReason());
        
        try {
            // 1. 查询原交易
            BankingTransaction originalTx = transactionRepository.findByTransactionId(event.getTransactionId());
            
            if (originalTx == null) {
                log.warn("原交易不存在,无法补偿: transactionId={}", event.getTransactionId());
                return;
            }
            
            // 2. 执行补偿操作
            if (originalTx.getTransactionType() == TransactionType.TRANSFER) {
                // 执行反向转账
                TransferRequest compensationRequest = TransferRequest.builder()
                    .fromAccount(originalTx.getToAccount())
                    .toAccount(originalTx.getFromAccount())
                    .amount(originalTx.getAmount())
                    .currency(originalTx.getCurrency())
                    .description("交易补偿: " + event.getReason())
                    .build();
                
                BankingTransactionResult result = processCoreTransfer(compensationRequest);
                
                if (result.isSuccess()) {
                    log.info("事务补偿成功: originalTx={}, compensationTx={}", 
                        event.getTransactionId(), result.getTransactionId());
                } else {
                    log.error("事务补偿失败: originalTx={}", event.getTransactionId());
                    alertService.sendCompensationFailureAlert(event.getTransactionId(), result.getErrorMessage());
                }
            }
            
        } catch (Exception e) {
            log.error("事务补偿异常: transactionId={}", event.getTransactionId(), e);
            alertService.sendCompensationExceptionAlert(event.getTransactionId(), e);
        }
    }
}

2. 电商订单系统事务设计

// 电商订单系统事务处理
@Service
public class EcommerceOrderTransactionService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryRepository inventoryRepository;
    
    @Autowired
    private PaymentRepository paymentRepository;
    
    /**
     * 订单创建事务:涉及多个业务环节
     */
    @Transactional(
        isolation = Isolation.READ_COMMITTED,
        propagation = Propagation.REQUIRED,
        timeout = 60,
        rollbackFor = {OrderException.class, InventoryException.class, PaymentException.class}
    )
    public OrderCreationResult createOrderTransaction(CreateOrderRequest request) {
        String orderNo = generateOrderNo();
        log.info("开始订单创建事务: orderNo={}, userId={}", orderNo, request.getUserId());
        
        try {
            // 1. 参数验证
            validateOrderRequest(request);
            
            // 2. 库存预检(悲观锁)
            Map<Long, ProductInventory> lockedInventories = lockAndCheckInventory(request.getItems());
            
            // 3. 价格计算
            PriceCalculationResult priceResult = calculateOrderPrice(request);
            
            // 4. 创建订单
            Order order = Order.builder()
                .orderNo(orderNo)
                .userId(request.getUserId())
                .items(convertToOrderItems(request.getItems()))
                .originalAmount(priceResult.getOriginalAmount())
                .discountAmount(priceResult.getDiscountAmount())
                .finalAmount(priceResult.getFinalAmount())
                .status(OrderStatus.PENDING_PAYMENT)
                .createTime(LocalDateTime.now())
                .build();
            
            order = orderRepository.save(order);
            
            // 5. 扣减库存
            deductInventory(lockedInventories, order.getItems());
            
            // 6. 应用优惠券
            if (request.getCouponIds() != null && !request.getCouponIds().isEmpty()) {
                applyCoupons(order, request.getCouponIds());
            }
            
            // 7. 使用积分
            if (request.getPointsToUse() != null && request.getPointsToUse() > 0) {
                usePoints(order, request.getPointsToUse());
            }
            
            // 8. 记录订单创建日志
            recordOrderCreationLog(order);
            
            // 9. 发送订单创建事件(用于后续异步处理)
            publishOrderCreatedEvent(order);
            
            log.info("订单创建事务成功: orderNo={}, amount={}", orderNo, order.getFinalAmount());
            
            return OrderCreationResult.success(orderNo, order.getFinalAmount());
            
        } catch (OrderException | InventoryException | PaymentException e) {
            log.error("订单创建业务异常: orderNo={}, error={}", orderNo, e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("订单创建系统异常: orderNo={}", orderNo, e);
            throw new OrderCreationException("订单创建失败", e);
        }
    }
    
    /**
     * 订单支付事务
     */
    @Transactional
    public PaymentResult processOrderPayment(PaymentRequest request) {
        log.info("开始订单支付事务: orderNo={}, amount={}", request.getOrderNo(), request.getAmount());
        
        try {
            // 1. 获取订单(加锁)
            Order order = orderRepository.findByOrderNoForUpdate(request.getOrderNo());
            
            if (order == null) {
                throw new OrderNotFoundException("订单不存在: " + request.getOrderNo());
            }
            
            // 2. 验证订单状态
            if (order.getStatus() != OrderStatus.PENDING_PAYMENT) {
                throw new InvalidOrderStatusException("订单状态不正确: " + order.getStatus());
            }
            
            // 3. 验证支付金额
            if (!order.getFinalAmount().equals(request.getAmount())) {
                throw new PaymentAmountMismatchException(
                    String.format("支付金额不匹配: expected=%s, actual=%s", 
                        order.getFinalAmount(), request.getAmount())
                );
            }
            
            // 4. 创建支付记录
            Payment payment = Payment.builder()
                .paymentNo(generatePaymentNo())
                .orderNo(order.getOrderNo())
                .userId(order.getUserId())
                .amount(request.getAmount())
                .paymentMethod(request.getPaymentMethod())
                .status(PaymentStatus.PROCESSING)
                .createTime(LocalDateTime.now())
                .build();
            
            payment = paymentRepository.save(payment);
            
            // 5. 调用支付网关
            GatewayPaymentResult gatewayResult = callPaymentGateway(request);
            
            // 6. 更新支付状态
            if (gatewayResult.isSuccess()) {
                payment.setStatus(PaymentStatus.SUCCESS);
                payment.setGatewayTransactionId(gatewayResult.getTransactionId());
                payment.setPaymentTime(LocalDateTime.now());
                paymentRepository.update(payment);
                
                // 7. 更新订单状态
                updateOrderStatusAfterPayment(order, PaymentStatus.SUCCESS);
                
                // 8. 确认库存扣减
                confirmInventoryDeduction(order);
                
                // 9. 发送支付成功通知
                sendPaymentSuccessNotification(order, payment);
                
                log.info("订单支付成功: orderNo={}, paymentNo={}", order.getOrderNo(), payment.getPaymentNo());
                
                return PaymentResult.success(payment.getPaymentNo());
                
            } else {
                // 支付失败
                payment.setStatus(PaymentStatus.FAILED);
                payment.setErrorMessage(gatewayResult.getErrorMessage());
                paymentRepository.update(payment);
                
                // 回滚库存
                rollbackInventoryDeduction(order);
                
                // 恢复优惠券和积分
                restoreCouponsAndPoints(order);
                
                // 更新订单状态
                updateOrderStatusAfterPayment(order, PaymentStatus.FAILED);
                
                log.warn("订单支付失败: orderNo={}, error={}", order.getOrderNo(), gatewayResult.getErrorMessage());
                
                return PaymentResult.failed(gatewayResult.getErrorMessage());
            }
            
        } catch (PaymentException e) {
            log.error("支付业务异常: orderNo={}, error={}", request.getOrderNo(), e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("订单支付系统异常: orderNo={}", request.getOrderNo(), e);
            throw new PaymentProcessingException("支付处理失败", e);
        }
    }
    
    /**
     * 订单取消事务
     */
    @Transactional
    public OrderCancellationResult cancelOrder(CancelOrderRequest request) {
        log.info("开始订单取消事务: orderNo={}, reason={}", request.getOrderNo(), request.getReason());
        
        try {
            // 1. 获取订单(加锁)
            Order order = orderRepository.findByOrderNoForUpdate(request.getOrderNo());
            
            if (order == null) {
                throw new OrderNotFoundException("订单不存在: " + request.getOrderNo());
            }
            
            // 2. 验证订单状态
            if (!isOrderCancellable(order.getStatus())) {
                throw new InvalidOrderStatusException(
                    String.format("订单当前状态不允许取消: status=%s", order.getStatus())
                );
            }
            
            // 3. 处理退款(如果已支付)
            if (order.getStatus() == OrderStatus.PAID || order.getStatus() == OrderStatus.SHIPPED) {
                processOrderRefund(order);
            }
            
            // 4. 恢复库存
            restoreInventory(order);
            
            // 5. 恢复优惠券
            if (order.getUsedCoupons() != null) {
                restoreUsedCoupons(order);
            }
            
            // 6. 恢复积分
            if (order.getUsedPoints() > 0) {
                restoreUsedPoints(order);
            }
            
            // 7. 更新订单状态
            order.setStatus(OrderStatus.CANCELLED);
            order.setCancelTime(LocalDateTime.now());
            order.setCancelReason(request.getReason());
            order.setCancelledBy(request.getCancelledBy());
            orderRepository.update(order);
            
            // 8. 记录取消日志
            recordOrderCancellationLog(order, request);
            
            // 9. 发送订单取消通知
            sendOrderCancellationNotification(order);
            
            log.info("订单取消事务成功: orderNo={}", request.getOrderNo());
            
            return OrderCancellationResult.success(request.getOrderNo());
            
        } catch (OrderException e) {
            log.error("订单取消业务异常: orderNo={}, error={}", request.getOrderNo(), e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("订单取消系统异常: orderNo={}", request.getOrderNo(), e);
            throw new OrderCancellationException("订单取消失败", e);
        }
    }
}

3. 库存管理系统事务设计

// 库存管理系统事务处理
@Service
public class InventoryTransactionService {
    
    @Autowired
    private InventoryRepository inventoryRepository;
    
    @Autowired
    private InventoryTransactionRepository transactionRepository;
    
    /**
     * 库存扣减事务:高并发场景
     */
    @Transactional(
        isolation = Isolation.READ_COMMITTED,
        propagation = Propagation.REQUIRED,
        timeout = 10,
        rollbackFor = {InventoryException.class}
    )
    public InventoryDeductionResult deductInventory(DeductInventoryRequest request) {
        log.info("开始库存扣减事务: productId={}, quantity={}, orderId={}", 
            request.getProductId(), request.getQuantity(), request.getOrderId());
        
        try {
            // 1. 获取库存信息(加锁)
            ProductInventory inventory = inventoryRepository.findByProductIdForUpdate(request.getProductId());
            
            if (inventory == null) {
                throw new ProductNotFoundException("商品不存在: " + request.getProductId());
            }
            
            // 2. 验证库存充足性
            if (inventory.getAvailableQuantity() < request.getQuantity()) {
                throw new InsufficientInventoryException(
                    String.format("库存不足: productId=%s, available=%s, required=%s",
                        request.getProductId(), inventory.getAvailableQuantity(), request.getQuantity())
                );
            }
            
            // 3. 检查库存状态
            if (inventory.getStatus() != InventoryStatus.AVAILABLE) {
                throw new InventoryStatusException("库存状态异常: " + inventory.getStatus());
            }
            
            // 4. 执行库存扣减
            int updatedRows = inventoryRepository.deductInventory(
                request.getProductId(),
                request.getQuantity(),
                inventory.getVersion()
            );
            
            if (updatedRows == 0) {
                throw new ConcurrentModificationException("库存并发修改,请重试");
            }
            
            // 5. 记录库存变动
            InventoryTransaction transaction = InventoryTransaction.builder()
                .transactionId(generateTransactionId())
                .productId(request.getProductId())
                .quantityChange(-request.getQuantity())
                .transactionType(InventoryTransactionType.ORDER_DEDUCTION)
                .orderId(request.getOrderId())
                .beforeQuantity(inventory.getAvailableQuantity())
                .afterQuantity(inventory.getAvailableQuantity() - request.getQuantity())
                .createTime(LocalDateTime.now())
                .build();
            
            transactionRepository.save(transaction);
            
            // 6. 更新库存统计
            updateInventoryStatistics(inventory, request.getQuantity());
            
            log.info("库存扣减事务成功: productId={}, quantity={}, transactionId={}", 
                request.getProductId(), request.getQuantity(), transaction.getTransactionId());
            
            return InventoryDeductionResult.success(
                transaction.getTransactionId(),
                inventory.getAvailableQuantity() - request.getQuantity()
            );
            
        } catch (InventoryException e) {
            log.error("库存业务异常: productId={}, error={}", request.getProductId(), e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("库存扣减系统异常: productId={}", request.getProductId(), e);
            throw new InventoryDeductionException("库存扣减失败", e);
        }
    }
    
    /**
     * 批量库存扣减:秒杀场景
     */
    @Transactional
    public BatchDeductionResult batchDeductInventory(BatchDeductionRequest request) {
        log.info("开始批量库存扣减: productId={}, totalQuantity={}, orderCount={}", 
            request.getProductId(), request.getTotalQuantity(), request.getOrders().size());
        
        try {
            // 1. 获取商品库存(加锁)
            ProductInventory inventory = inventoryRepository.findByProductIdForUpdate(request.getProductId());
            
            // 2. 验证总库存
            if (inventory.getAvailableQuantity() < request.getTotalQuantity()) {
                throw new InsufficientInventoryException("总库存不足");
            }
            
            // 3. 创建批量扣减任务
            BatchDeductionTask task = BatchDeductionTask.builder()
                .taskId(generateTaskId())
                .productId(request.getProductId())
                .totalQuantity(request.getTotalQuantity())
                .orderCount(request.getOrders().size())
                .status(BatchStatus.PROCESSING)
                .createTime(LocalDateTime.now())
                .build();
            
            task = inventoryRepository.saveBatchTask(task);
            
            // 4. 批量扣减库存
            int deductedQuantity = 0;
            List<InventoryTransaction> transactions = new ArrayList<>();
            
            for (OrderInventory order : request.getOrders()) {
                // 扣减单个订单库存
                int updatedRows = inventoryRepository.deductInventory(
                    request.getProductId(),
                    order.getQuantity(),
                    inventory.getVersion()
                );
                
                if (updatedRows > 0) {
                    deductedQuantity += order.getQuantity();
                    
                    // 记录交易
                    InventoryTransaction transaction = InventoryTransaction.builder()
                        .transactionId(generateTransactionId())
                        .productId(request.getProductId())
                        .quantityChange(-order.getQuantity())
                        .transactionType(InventoryTransactionType.BATCH_DEDUCTION)
                        .orderId(order.getOrderId())
                        .batchTaskId(task.getTaskId())
                        .createTime(LocalDateTime.now())
                        .build();
                    
                    transactions.add(transaction);
                }
            }
            
            // 5. 批量保存交易记录
            if (!transactions.isEmpty()) {
                transactionRepository.batchSave(transactions);
            }
            
            // 6. 更新批量任务状态
            task.setProcessedQuantity(deductedQuantity);
            task.setSuccessCount(transactions.size());
            task.setStatus(deductedQuantity == request.getTotalQuantity() ? BatchStatus.SUCCESS : BatchStatus.PARTIAL_SUCCESS);
            task.setCompleteTime(LocalDateTime.now());
            inventoryRepository.updateBatchTask(task);
            
            log.info("批量库存扣减完成: taskId={}, deducted={}, total={}", 
                task.getTaskId(), deductedQuantity, request.getTotalQuantity());
            
            return BatchDeductionResult.success(task.getTaskId(), deductedQuantity);
            
        } catch (Exception e) {
            log.error("批量库存扣减异常", e);
            throw new BatchDeductionException("批量库存扣减失败", e);
        }
    }
    
    /**
     * 库存回滚事务
     */
    @Transactional
    public InventoryRollbackResult rollbackInventory(InventoryRollbackRequest request) {
        log.info("开始库存回滚事务: transactionId={}, productId={}, quantity={}", 
            request.getOriginalTransactionId(), request.getProductId(), request.getQuantity());
        
        try {
            // 1. 查询原交易
            InventoryTransaction originalTx = transactionRepository.findByTransactionId(request.getOriginalTransactionId());
            
            if (originalTx == null) {
                throw new TransactionNotFoundException("原交易不存在: " + request.getOriginalTransactionId());
            }
            
            // 2. 验证回滚条件
            if (originalTx.getTransactionType() != InventoryTransactionType.ORDER_DEDUCTION) {
                throw new InvalidRollbackException("该交易类型不支持回滚: " + originalTx.getTransactionType());
            }
            
            if (originalTx.getRollbackStatus() == RollbackStatus.ROLLED_BACK) {
                log.warn("交易已回滚,跳过: transactionId={}", request.getOriginalTransactionId());
                return InventoryRollbackResult.skipped("交易已回滚");
            }
            
            // 3. 获取库存信息(加锁)
            ProductInventory inventory = inventoryRepository.findByProductIdForUpdate(request.getProductId());
            
            // 4. 执行库存回滚
            int updatedRows = inventoryRepository.increaseInventory(
                request.getProductId(),
                request.getQuantity(),
                inventory.getVersion()
            );
            
            if (updatedRows == 0) {
                throw new ConcurrentModificationException("库存并发修改,请重试");
            }
            
            // 5. 记录回滚交易
            InventoryTransaction rollbackTx = InventoryTransaction.builder()
                .transactionId(generateTransactionId())
                .productId(request.getProductId())
                .quantityChange(request.getQuantity())
                .transactionType(InventoryTransactionType.ROLLBACK)
                .orderId(originalTx.getOrderId())
                .relatedTransactionId(originalTx.getTransactionId())
                .beforeQuantity(inventory.getAvailableQuantity())
                .afterQuantity(inventory.getAvailableQuantity() + request.getQuantity())
                .createTime(LocalDateTime.now())
                .build();
            
            transactionRepository.save(rollbackTx);
            
            // 6. 更新原交易回滚状态
            originalTx.setRollbackStatus(RollbackStatus.ROLLED_BACK);
            originalTx.setRollbackTime(LocalDateTime.now());
            originalTx.setRollbackReason(request.getReason());
            transactionRepository.update(originalTx);
            
            // 7. 更新库存统计
            updateInventoryStatisticsAfterRollback(inventory, request.getQuantity());
            
            log.info("库存回滚事务成功: rollbackTx={}, originalTx={}", 
                rollbackTx.getTransactionId(), originalTx.getTransactionId());
            
            return InventoryRollbackResult.success(rollbackTx.getTransactionId());
            
        } catch (InventoryException e) {
            log.error("库存回滚业务异常: transactionId={}, error={}", 
                request.getOriginalTransactionId(), e.getMessage());
            throw e;
            
        } catch (Exception e) {
            log.error("库存回滚系统异常: transactionId={}", request.getOriginalTransactionId(), e);
            throw new InventoryRollbackException("库存回滚失败", e);
        }
    }
}

事务性数据存储架构演进路径

业务复杂
性能要求
智能化
云原生
特点
特点
特点
特点
特点
单体事务
分布式事务
最终一致性
自适应事务
弹性事务
简单直接
跨服务协调
性能平衡
智能选择
弹性扩展

总结

事务性数据存储架构法则是构建可靠业务系统的核心原则。通过使用RDBMS/SQL数据库的完整事务机制,我们能够:

核心原则

  1. 强一致性保证:通过ACID特性确保数据的完整性和一致性
  2. 隔离级别选择:根据业务场景选择合适的事务隔离级别
  3. 异常处理机制:建立完善的事务异常处理和补偿机制
  4. 并发控制:通过锁机制和MVCC实现高效的并发控制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值