> Что происходит при обновлении нескольких строк в одном запросе в базе данных (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Ozon
Стек: Go
> Пример ответа
При обновлении нескольких строк в одном SQL-запросе (например, UPDATE users SET status = 'active' WHERE id IN (1,2,3)) в базе данных происходит несколько ключевых процессов:
-
Транзакционная изоляция: Запрос выполняется в рамках одной транзакции (если не указано иное). Это гарантирует атомарность - либо обновятся все строки, либо ни одна (при ошибке). В Go с драйверами типа
database/sqlэто поведение по умолчанию, если не используется ручное управление транзакциями. -
Блокировки строк: СУБД (например, PostgreSQL или MySQL с InnoDB) накладывает блокировки на каждую обновляемую строку (row-level locks). Это предотвращает конфликты с параллельными запросами. В Go при работе с высоконагруженными системами важно учитывать, что длительные блокировки могут вызвать deadlock.
-
Журналирование: Каждое изменение записывается в WAL (Write-Ahead Log) для обеспечения durability. При сбое питания база данных восстановит состояние до начала запроса.
-
Индексы и триггеры: Если на таблице есть индексы, они обновляются для каждой строки. Триггеры (например,
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 остаётся простым и надёжным выбором для небольших наборов данных.
> Похожие задачи по Go
Как написать запрос, который выберет названия всех книг с более чем тремя авторами
Какой индекс построить для запроса с условиями на несколько столбцов
Как понять, что код отработал правильно
Как в Go встраивание заменяет наследование
> Похожие задачи по backend
Как написать запрос, который выберет названия всех книг с более чем тремя авторами
Какой индекс построить для запроса с условиями на несколько столбцов
Как понять, что код отработал правильно
Как в Go встраивание заменяет наследование
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью