OOro

事务

回调事务、手动事务、嵌套 savepoint、重试和行锁。

回调事务

err := db.Transaction(ctx, func(tx *oro.DB) error {
    _, err := tx.Use[Product]().Create(ctx, &Product{Code: "P001"})
    return err
})

返回错误会回滚,返回 nil 会提交。

嵌套事务

嵌套事务在驱动支持时使用 savepoint。

err := db.Transaction(ctx, func(tx *oro.DB) error {
    if _, err := tx.Table("orders").Create(ctx, oro.Map{"status": "draft"}); err != nil {
        return err
    }

    return tx.Transaction(ctx, func(inner *oro.DB) error {
        _, err := inner.Table("order_logs").Create(ctx, oro.Map{"message": "created"})
        return err
    })
})

手动事务

tx, err := db.Begin(ctx)
if err != nil { return err }

committed := false
defer func() {
    if !committed {
        _ = tx.Rollback(ctx)
    }
}()

if _, err := tx.Use[Product]().Create(ctx, product); err != nil {
    return err
}

if err := tx.Commit(ctx); err != nil {
    return err
}
committed = true

普通业务优先用回调事务;手动事务适合事务边界跨多个 helper 的场景。

行锁

err := db.Transaction(ctx, func(tx *oro.DB) error {
    product, err := tx.Use[Product]().Where("ID", id).LockForUpdate().First(ctx)
    if err != nil || product == nil {
        return err
    }

    _, err = tx.Use[Product]().Where("ID", product.ID).Update(ctx, oro.Map{
        "Stock": oro.Decrement(1),
    })
    return err
})

锁必须在事务内使用。支持 LockForUpdateLockForShareNoWaitSkipLocked

重试和超时

db, err := oro.Open(oro.Config{
    Timeout: oro.TimeoutConfig{
        Query:       5 * time.Second,
        Transaction: 10 * time.Second,
    },
    Retry: oro.RetryConfig{
        TxDeadlockAttempts: 3,
    },
})

也可以设置单次查询超时:

rows, err := db.Use[Product]().Timeout(2 * time.Second).Get(ctx)
编辑此页