Pular para o conteúdo principal
Versão: Em desenvolvimento — v0.2.3

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 txCtx dentro 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.