Появление крупных хранилищ и потоков данных (ETL, миграции) потребовало не просто загружать сотни тысяч строк, но и гарантировать, что данные либо загрузятся полностью, либо не загрузится ничего. В SQL это реализуется через атомарные bulk-операции с помощью транзакций.
При массовой вставке (Bulk Insert) риск ошибки выше — один некорректный ряд может испортить всю загрузку или привести к частичной вставке. Это недопустимо для финансовых, логистических и других критичных систем.
Практика — оборачивать bulk-операцию в транзакцию, использовать подходящие специальные команды (BULK INSERT, COPY) и ловить/логировать ошибки. Важно: при ошибке любой строки происходит откат всего блока:
Пример для SQL Server:
BEGIN TRAN; BULK INSERT Customers FROM 'C:\data\customers.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = ' ', FIRSTROW = 2 ); IF @@ERROR <> 0 ROLLBACK TRAN; ELSE COMMIT TRAN;
В PostgreSQL (пример с COPY):
BEGIN; COPY products FROM '/tmp/products.csv' DELIMITER ',' CSV HEADER; COMMIT;
Ключевые особенности:
Влияет ли размер транзакции при Bulk Insert на производительность и блокировки?
Да, при слишком больших объемах можно получить длительную блокировку, переполнить логи транзакций и замедлить сервер. Лучшее — загружать порциями (batch), например по 10000 строк за транзакцию.
Является ли Bulk Insert всегда транзакционным по умолчанию во всех СУБД?
Нет, в некоторых СУБД (например, MySQL) команда bulk insert не всегда автоматически атомарна — требуется обернуть её в BEGIN/COMMIT вручную, иначе возможна частичная загрузка.
Можно ли гарантировать целостность внешних ключей при массовой вставке?
Да, только если порядок загрузки соблюдается: сначала родительские таблицы, потом дочерние, либо временно отключать констрейнты. Ошибка внешнего ключа откатит всю транзакцию bulk insert.
В процессе загрузки клиентов файл с ошибкой в одной строке привёл к частичной загрузке — к концу дня база и внешний источник рассинхронизировались
Плюсы:
Файл предварительно проверяется на ошибки, Bulk insert разбит на порции по 5000 строк, каждая порция в своей транзакции. Логи ошибок сохраняются для дальнейшего анализа.
Плюсы: