Transações
sqlDB.NewTransaction() cria um bloco que confirma as operações quando o callback retorna nil e executa rollback quando ele retorna erro.
Exemplo
func Transfer(ctx context.Context, fromID, toID string, amount int64) error {
transaction := sqlDB.NewTransaction(sql.LevelSerializable)
return transaction.Execute(ctx, func(txCtx context.Context) error {
if err := sqlDB.NewStatement(
txCtx,
"UPDATE accounts SET balance = balance - $1 WHERE id = $2",
amount,
fromID,
).Execute(); err != nil {
return fmt.Errorf("debit account: %w", err)
}
if err := sqlDB.NewStatement(
txCtx,
"UPDATE accounts SET balance = balance + $1 WHERE id = $2",
amount,
toID,
).Execute(); err != nil {
return fmt.Errorf("credit account: %w", err)
}
return nil
})
}
Use sempre o txCtx recebido no callback. NewQuery e NewStatement reconhecem a transação armazenada nesse contexto.
Isolamento
Sem argumento, o SDK usa sql.LevelDefault:
transaction := sqlDB.NewTransaction()
Também é possível informar um nível suportado pelo driver:
sql.LevelReadUncommitted;sql.LevelReadCommitted;sql.LevelRepeatableRead;sql.LevelSerializable.
Se mais de um nível for fornecido, apenas o primeiro é usado.
Erros e rollback
Qualquer erro retornado pelo callback provoca rollback:
return transaction.Execute(ctx, func(txCtx context.Context) error {
if err := validateBalance(txCtx); err != nil {
return err
}
return persist(txCtx)
})
Um panic também chega ao defer tx.Rollback(), mas deve ser recuperado pela camada apropriada. Prefira retornar erros com contexto.
Limites
- O helper usa a instância global inicializada por
sqlDB.Initialize(). - Não misture o contexto original com
txCtxdentro do callback. - O SDK não oferece savepoints ou transações aninhadas.
- Operações externas, como HTTP ou mensageria, não participam da transação SQL.