> Что происходит при обновлении нескольких строк в одном запросе в базе данных (Go)

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

Компании: Ozon

Стек: Go

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

При обновлении нескольких строк в одном SQL-запросе (например, UPDATE users SET status = 'active' WHERE id IN (1,2,3)) в базе данных происходит несколько ключевых процессов:

  1. Транзакционная изоляция: Запрос выполняется в рамках одной транзакции (если не указано иное). Это гарантирует атомарность - либо обновятся все строки, либо ни одна (при ошибке). В Go с драйверами типа database/sql это поведение по умолчанию, если не используется ручное управление транзакциями.

  2. Блокировки строк: СУБД (например, PostgreSQL или MySQL с InnoDB) накладывает блокировки на каждую обновляемую строку (row-level locks). Это предотвращает конфликты с параллельными запросами. В Go при работе с высоконагруженными системами важно учитывать, что длительные блокировки могут вызвать deadlock.

  3. Журналирование: Каждое изменение записывается в WAL (Write-Ahead Log) для обеспечения durability. При сбое питания база данных восстановит состояние до начала запроса.

  4. Индексы и триггеры: Если на таблице есть индексы, они обновляются для каждой строки. Триггеры (например, BEFORE UPDATE) срабатывают для каждой строки отдельно, что может замедлить выполнение.

Пример в Go:

GO
_, err := db.Exec("UPDATE users SET balance = balance + 100 WHERE id = ANY($1)", pg.Array([]int{1, 2, 3}))

Здесь важно использовать подготовленные запросы и избегать конкатенации строк для защиты от SQL-инъекций.

Потенциальные проблемы:

  • Deadlocks: Если два запроса блокируют строки в разном порядке, может возникнуть взаимная блокировка. Решение - всегда обновлять строки в одном порядке (например, по возрастанию ID).
  • Производительность: Массовые обновления лучше выполнять в пакетном режиме (batch update), разбивая на части по 1000-5000 строк, чтобы не перегружать блокировки и журнал.

В Go для массовых обновлений часто используют COPY (в PostgreSQL) или пакетные UPDATE с UNION ALL, но стандартный UPDATE с IN остаётся простым и надёжным выбором для небольших наборов данных.

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

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