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

GORM 跨库事务处理

GORM 原生事务仅支持单库 ACID,跨库事务需借助补偿机制或 Saga 模式实现最终一致性。

单库事务基础

标准事务用法

Go
err := db.Transaction(func(tx *gorm.DB) error {
    if err := tx.Create(&user).Error; err != nil {
        return err
    }
    if err := tx.Create(&order).Error; err != nil {
        return err
    }
    return nil
})

跨库事务限制

不支持分布式事务

Go
// 错误示例:两个不同数据库无法使用同一事务
tx1 := db1.Begin()
tx2 := db2.Begin()

tx1.Create(&user)   // db1 操作
tx2.Create(&order)  // db2 操作

// 无法同时提交/回滚两个事务

注意: GORM 不支持跨库原子事务,需采用补偿机制或外部协调器实现最终一致性。

手动补偿事务

失败回滚 + 补偿操作

Go
func CrossDBOperation(db1, db2 *gorm.DB) error {
    tx1 := db1.Begin()
    defer func() {
        if r := recover(); r != nil {
            tx1.Rollback()
        }
    }()
    
    // db1 操作
    if err := tx1.Create(&user).Error; err != nil {
        tx1.Rollback()
        return err
    }
    
    tx2 := db2.Begin()
    defer func() {
        if r := recover(); r != nil {
            tx2.Rollback()
            // 补偿:回滚 db1 操作
            tx1.Rollback()
        }
    }()
    
    // db2 操作
    if err := tx2.Create(&order).Error; err != nil {
        tx2.Rollback()
        // 补偿:回滚 db1
        tx1.Rollback()
        return err
    }
    
    // 提交事务(顺序提交,无原子保证)
    if err := tx1.Commit().Error; err != nil {
        tx2.Rollback()
        return err
    }
    return tx2.Commit().Error
}

Saga 模式实现

步骤定义与补偿

Go
type SagaStep struct {
    Action    func() error
    Compensate func() error
}

type Saga struct {
    Steps []SagaStep
}

func (s *Saga) AddStep(action, compensate func() error) {
    s.Steps = append(s.Steps, SagaStep{
        Action:    action,
        Compensate: compensate,
    })
}

func (s *Saga) Execute() error {
    executed := []int{}
    
    // 正向执行
    for i, step := range s.Steps {
        if err := step.Action(); err != nil {
            // 失败则逆向补偿
            for j := len(executed) - 1; j >= 0; j-- {
                idx := executed[j]
                s.Steps[idx].Compensate()
            }
            return err
        }
        executed = append(executed, i)
    }
    return nil
}

// 使用
saga := &Saga{}
saga.AddStep(
    func() error { return db1.Create(&user).Error },
    func() error { return db1.Delete(&user, user.ID).Error },
)
saga.AddStep(
    func() error { return db2.Create(&order).Error },
    func() error { return db2.Delete(&order, order.ID).Error },
)

err := saga.Execute()

异步补偿队列

基于消息队列的最终一致性

Go
type PendingCompensation struct {
    ID          uint `gorm:"primaryKey"`
    ServiceName string
    Payload     string `gorm:"type:text"`
    Status      string // pending, success, failed
    RetryCount  int
}

// 记录待补偿操作
func RecordCompensation(db *gorm.DB, service string, payload string) error {
    return db.Create(&PendingCompensation{
        ServiceName: service,
        Payload:     payload,
        Status:      "pending",
    }).Error
}

// 定时任务执行补偿
func ProcessCompensations(db *gorm.DB) {
    var pendings []PendingCompensation
    db.Where("status = ? AND retry_count < ?", "pending", 3).Find(&pendings)
    
    for _, p := range pendings {
        err := ExecuteCompensation(p.ServiceName, p.Payload)
        if err == nil {
            db.Model(&p).Update("status", "success")
        } else {
            db.Model(&p).Update("retry_count", gorm.Expr("retry_count + ?", 1))
        }
    }
}

TCC 模式简述

Try-Confirm-Cancel 三阶段

Go
// Try: 预留资源
// Confirm: 确认提交
// Cancel: 取消释放

type TCCService interface {
    Try(ctx context.Context) error
    Confirm(ctx context.Context) error
    Cancel(ctx context.Context) error
}

// 协调器执行
func ExecuteTCC(services []TCCService) error {
    // 全部 Try
    for _, s := range services {
        if err := s.Try(context.Background()); err != nil {
            // 失败则全部 Cancel
            for _, s := range services {
                s.Cancel(context.Background())
            }
            return err
        }
    }
    // 全部 Confirm
    for _, s := range services {
        s.Confirm(context.Background())
    }
    return nil
}

注意: TCC 需业务手动实现 Try/Confirm/Cancel 逻辑,适合对一致性要求高的场景。

要点总结

  • GORM 原生事务仅支持单库,跨库需自行实现补偿机制
  • 手动补偿方案:失败时逆向回滚已提交操作
  • Saga 模式通过步骤定义和补偿函数实现最终一致性
  • 异步补偿队列适合对实时性要求不高的场景
  • TCC 模式需业务实现三阶段逻辑,一致性更强但复杂度高

存放路径:D:\git2\jwdev\articles\GORM\专家\分库分表与多租户\跨库事务处理.md

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

← 上一篇 GORM 多租户数据隔离
下一篇 → GORM 数据一致性校验
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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