Auto Increment пропускает числа?

Примечание. Я новичок в базах данных и PHP

У меня есть столбец order, который установлен в auto increment и unique.

http://f.cl.ly/items/3u2D1l1j2l0j0A16450I/Image%202013-07-22%20at%207.00.15%20PM.png

В моем PHP script я использую AJAX для получения новых данных, но проблема заключается в том, что order пропускает числа и существенно выше, что заставляет меня вручную обновлять числа при вставке данных, В этом случае я бы изменил значение 782 на 38.

http://f.cl.ly/items/0N2J1w1Y310E2H2o0m05/Image%202013-07-22%20at%206.49.20%20PM.png

$SQL = "INSERT IGNORE INTO `read`(`title`,`url`) VALUES\n ".implode( "\n,",array_reverse( $sql_values ) );

Как я могу заставить его увеличивать +1?

Ответ 1

По умолчанию поведение auto_increment в MySQL 5.1 и более поздних версиях будет "потерять" значения автоматического увеличения, если INSERT завершится с ошибкой. То есть, он увеличивается каждый раз на 1, но не отменяет приращение, если INSERT терпит неудачу. Это редкость потерять ~ 750 значений, но не невозможно (я проконсультировался для сайта, который пропускал 1500 для каждого INSERT, который преуспел).

Вы можете изменить innodb_autoinc_lock_mode=0, чтобы использовать поведение MySQL 5.0 и в некоторых случаях избегать потери значений. Подробнее см. http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html.

Еще одна вещь, которую нужно проверить, - это значение переменной auto_increment_increment config. Он по умолчанию 1, но вы, возможно, изменили это. Опять же, очень редко, чтобы установить его на что-то выше 1 или 2, но возможно.

Я согласен с другими комментаторами, столбцы autinc предназначены для того, чтобы быть уникальными, но не обязательно последовательными. Вы, вероятно, не должны беспокоиться об этом так сильно, если вы не продвигаете значение autoinc так быстро, что можете выбежать из диапазона INT (это случилось со мной).


Как именно вы исправили это пропущение 1500 навсегда?

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

Исправление заключалось в том, чтобы сначала выполнить SELECT, чтобы проверить наличие значения, прежде чем пытаться ВСТАВИТЬ его. Это противоречит общей мудрости, которая заключается в том, чтобы просто попробовать INSERT и обработать любое дублирующее ключевое исключение. Но в этом случае побочный эффект неудавшегося INSERT привел к потере значения auto-inc. Выполнение SELECT сначала устранило почти все такие исключения.

Но вам также придется обрабатывать возможное исключение, даже если вы сначала SELECT. У вас все еще есть состояние гонки.

Вы правы! innodb_autoinc_lock_mode = 0 работал как шарм.

В вашем случае я хотел бы знать, почему так много вставок терпят неудачу. Я подозреваю, что, как и многие разработчики SQL, вы не проверяете статус успеха после того, как выполняете свои INSERT в обработчике AJAX, поэтому никогда не знаете, что многие из них терпят неудачу.

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

Ответ 2

После изменения 782 в 38 вы можете reset автоинкремент с ALTER TABLE mytable AUTO_INCREMENT = 39. Таким образом, вы продолжаете в 39.

Однако вы должны проверить, почему ваш разрыв настолько высок, и соответствующим образом изменить ваш дизайн. Изменение состояния автоинформации не должно быть "по умолчанию".

Ответ 3

auto increment не заботится, если вы удаляете несколько строк - каждый раз, когда вы вставляете строку, значение увеличивается.

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

INSERT INTO tablename SET
    `order` = (SELECT max(`order`) + 1 FROM (SELECT * from tablename) t),
    ...

и если вы удалите строку, вы должны вручную упорядочить колонку заказа

Ответ 4

Я знаю, что на вопрос уже был дан ответ. Но если вы удалили строки в таблице раньше, mysql запомнит использованный ID/Number, потому что обычно ваше Auto increment уникально. Поэтому поэтому не создавайте повторяющиеся приращения. Чтобы переиндексировать и увеличивать с текущего максимального ID/целого числа, вы можете выполнить:

ALTER TABLE TableName AUTO_INCREMENT=(SELECT max(order) + 1 FROM tablename)