> Пример использования FOR UPDATE в PostgreSQL (Go, PostgreSQL)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Ozon

Стек: Go, PostgreSQL

> Пример ответа

FOR UPDATE в PostgreSQL используется для блокировки выбранных строк при выполнении SELECT, чтобы предотвратить их изменение другими транзакциями до завершения текущей. Это критично для сценариев с конкурентным доступом, например, при резервировании товаров или обработке очередей.

Пример на Go с использованием database/sql и pgx:

GO
package main
import (
"context"
"fmt"
"log"
"github.com/jackc/pgx/v5/pgxpool"
)
func reserveItem(ctx context.Context, pool *pgxpool.Pool, itemID int) error {
tx, err := pool.Begin(ctx)
if err != nil {
return fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback(ctx) // откат при ошибке
// Блокируем строку для обновления
var quantity int
err = tx.QueryRow(ctx,
`SELECT quantity FROM inventory WHERE id = $1 FOR UPDATE`, itemID).Scan(&quantity)
if err != nil {
return fmt.Errorf("select for update: %w", err)
}
if quantity <= 0 {
return fmt.Errorf("item out of stock")
}
// Обновляем количество
_, err = tx.Exec(ctx,
`UPDATE inventory SET quantity = quantity - 1 WHERE id = $1`, itemID)
if err != nil {
return fmt.Errorf("update: %w", err)
}
return tx.Commit(ctx)
}
func main() {
pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost/db")
if err != nil {
log.Fatal(err)
}
defer pool.Close()
if err := reserveItem(context.Background(), pool, 1); err != nil {
log.Printf("reservation failed: %v", err)
}
}

Ключевые моменты:

  • FOR UPDATE работает только внутри транзакции (блок BEGIN/COMMIT).

  • Блокировка снимается при завершении транзакции (commit или rollback).

  • Если другая транзакция уже держит блокировку на строке, текущая будет ждать (таймаут можно задать через NOWAIT или SKIP LOCKED).

  • В Go используйте pgxpool для управления пулом соединений и явные транзакции (Begin/Commit/Rollback).

Этот подход гарантирует атомарность операции "проверить и уменьшить остаток" без гонок данных.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью