Является ли объемная вставка атомарной? - PullRequest
4 голосов
/ 09 сентября 2010

У меня есть таблица с автоинкрементом первичного ключа. Я хочу вставить в него кучу данных и получить ключи для каждого из них без дополнительных запросов.

START TRANSACTION;
INSERT INTO table (value) VALUES (x),(y),(z);
SELECT LAST_INSERT_ID() AS last_id;
COMMIT;

Может ли MySQL гарантировать, что все данные будут вставлены в один непрерывный упорядоченный поток, чтобы я мог легко вычислить идентификаторы для каждого элемента?

id(z) = last_id;
id(y) = last_id - 1;
id(x) = last_id - 2;

Ответы [ 2 ]

2 голосов
/ 09 сентября 2010

Если вы начнете транзакцию, а затем вставите данные в таблицу, вся эта таблица будет заблокирована для этой транзакции (если только вы не начнете играть с уровнями изоляции транзакций и / или подсказками блокировки).

Это, в сущности, точка транзакций. Для предотвращения внешних операций, изменяющих (в любом случае) то, над чем вы работаете.

Этот тип «Table Lock» является поведением по умолчанию в большинстве случаев.

В необычных обстоятельствах вы можете обнаружить, что в СУБД были установлены определенные параметры, которые означают, что «нормальное» поведение по умолчанию (блокировка таблиц) - это не то, что происходит для этой конкретной установки. В этом случае вы должны иметь возможность переопределить значение по умолчанию, указав, что вы хотите блокировку таблицы как часть инструкции INSERT.

EDIT:

У меня большой опыт работы с MS-SQL Server и патчи на многих других РСУБД. Ни в одном из этих случаев я не нашел никаких гарантий того, что вставка произойдет в определенном порядке.

Одна из причин этого заключается в том, что часть SELECT для INSERT может вычисляться параллельно. Это будет означать, что данные, которые будут вставлены, готовы не в порядке.

Точно так же, когда вставляются особенно большие объемы данных, СУБД может определить, что новые данные будут занимать несколько страниц памяти или дискового пространства. Опять же, это может привести к параллельной работе.

Насколько мне известно, в MySQL есть функция типа row_number (), которую можно указать в запросе SELECT, результат которого можно сохранить в базе данных. После этого вы сможете полагаться на это поле (созданное вами), но не на поле идентификатора автоинкремента (созданное СУБД).

0 голосов
/ 09 сентября 2010

Насколько я знаю, это будет работать практически во всех SQL-движках.

...