Back to questions
Senior
5
Ты работал с транзакциями на уровне бизнес-процессов — SELECT FOR UPDATE, rollback при падении внешнего API?
Companies where asked
Штрафов нет
Answer from AI
sobes.tech AI
Да, работал с транзакциями на уровне бизнес-процессов в Go. Использовал SELECT FOR UPDATE для блокировки строк в базе данных, чтобы избежать гонок при параллельных операциях. Например, при резервировании товара в заказе сначала делал выборку с блокировкой, затем обновлял количество, и только после успешного взаимодействия с внешним API подтверждал транзакцию.
Если внешний API падал, то вызывал rollback транзакции, чтобы не сохранить изменения в базе и не оставить систему в неконсистентном состоянии.
Пример с использованием database/sql и PostgreSQL:
ctx := context.Background()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return err
}
// Блокируем строку
row := tx.QueryRowContext(ctx, "SELECT quantity FROM products WHERE id=$1 FOR UPDATE", productID)
var quantity int
if err := row.Scan(&quantity); err != nil {
tx.Rollback()
return err
}
if quantity < needed {
tx.Rollback()
return errors.New("not enough stock")
}
// Вызов внешнего API
if err := callExternalAPI(); err != nil {
tx.Rollback()
return err
}
// Обновляем количество
_, err = tx.ExecContext(ctx, "UPDATE products SET quantity = quantity - $1 WHERE id = $2", needed, productID)
if err != nil {
tx.Rollback()
return err
}
return tx.Commit()
Такой подход гарантирует атомарность бизнес-операции и согласованность данных.