Поведение MySQL AUTO_INCREMENT в многострочной вставке - PullRequest
8 голосов
/ 01 августа 2011

Я думаю, что ответ на мой вопрос очевиден, но, поскольку я не смог найти никакой документации, подтверждающей это, я подумал, что стоит спросить. По крайней мере, для записи.

Как мы все знаем, AUTO_INCREMENT поля увеличиваются каждый раз, когда выполняется оператор INSERT. И его значение можно получить с помощью функции LAST_INSERT_ID(). В MySQL's Manual также упоминается, что при многострочных вставках LAST_INSERT_ID() вернет первый идентификатор вставленных строк. Что я считаю хорошей идеей (действительно полезной).

Итак, мой вопрос:

Можно ли предположить, что в операторе INSERT IGNORE INTO с несколькими строками вставленные идентификаторы поля AUTO_INCREMENT всегда будут последовательными? Имейте в виду, что из-за модификатора IGNORE и многопользовательской природы сервера MySQL могут возникнуть разные сценарии.

Спасибо.

1 Ответ

7 голосов
/ 01 августа 2011

Нет, вы не можете предполагать это.Один из сценариев, в котором идентификаторы не будут последовательными, - это настройка репликации с несколькими хозяевами.Например, если в такой настройке существуют два сервера, один будет генерировать только четные автоматические идентификаторы, а другой - только нечетные идентификаторы (имейте в виду, что это всего лишь пример).

Однако, если ваша настройка не такая,тогда да.По крайней мере, в InnoDB вставки являются атомарными и ставятся в очередь при нацеливании на одну и ту же таблицу, поэтому идентификаторы из двух разных INSERT не будут чередоваться.(хотя это не задокументировано, поэтому полагаться на это ... немного рискованно)


Как я тестировал генерацию IGNORE INSERT ID:

mysql> CREATE TABLE  `ignoreinsert` (
    ->   `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `uq` int(10) unsigned NOT NULL,
    ->   PRIMARY KEY (`ID`),
    ->   UNIQUE KEY `uq` (`uq`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.19 sec)

mysql> INSERT INTO ignoreinsert VALUES (null,1),(null,2);
Query OK, 2 rows affected (0.10 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM ignoreinsert;
+----+----+
| ID | uq |
+----+----+
|  1 |  1 |
|  2 |  2 |
+----+----+
2 rows in set (0.00 sec)

mysql> INSERT IGNORE INTO ignoreinsert VALUES (null,3),(null,1),(null,4),(null,2),(null,5);
Query OK, 3 rows affected (0.08 sec)
Records: 5  Duplicates: 2  Warnings: 0

mysql> SELECT * FROM ignoreinsert;
+----+----+
| ID | uq |
+----+----+
|  1 |  1 |
|  2 |  2 |
|  3 |  3 |
|  4 |  4 |
|  5 |  5 |
+----+----+
5 rows in set (0.00 sec)
...