2013-07-22 4 views
11

Примечание: Я новичок в базах данных и PHPAuto Increment пропускает числа?

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

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

В моем PHP скрипт, я использую 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?

+0

Вы можете разместить структуру своей базы данных с некоторыми примерными данными, может быть? – Maximus2012

+4

«auto increment» - это не индекс строки **. Прерванные транзакции и удаленные записи будут «поглощать» продвижение. – user2246674

+0

Вы * можете * быть заинтересованы в [имитации] [ROW_NUMBER] (http://stackoverflow.com/questions/1895110/row-number-in-mysql), если вы хотите получить индекс строки по [n упорядоченному] результату - задавать. – user2246674

ответ

17

Поведение auto_increment по умолчанию в MySQL 5.1 и более поздний «потеряют» auto-increment values, если 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. По умолчанию это 1, но вы, возможно, изменили это. Опять же, очень редко, чтобы установить его на что-то выше 1 или 2, но возможно.

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


How exactly did you fix it skipping 1500 for ever insert?

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

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

Но у вас также необходимо обработать возможное исключение, даже если вы ВЫБЕРИТЕ первым. У вас все еще есть состояние гонки.

You're right! innodb_autoinc_lock_mode=0 worked like a charm.

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

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

+0

'Вам, вероятно, не стоит так беспокоиться об этом, если вы не так быстро продвигаете значение autoinc'а. Именно поэтому это происходит. Я использую AJAX для захвата новых данных за 2 секунды, и прирост увеличивается на количество строк, которые у меня есть. –

+0

Не уверен, что это на 100% актуально здесь, но интересно также: innodb также потеряет значение автоинкремента после перезапуска сервера (и восстановит его как «MAX (PK) + 1' при следующем запуске) – zerkms

+0

@zerkms, да, это правда, но это не следует заставлять InnoDB впоследствии пропускать большой диапазон значений. –

0

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

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

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

и если вы удалите строки, вы должны rearange столбца заказа вручную

+0

Я действительно думал, что могу сделать это, используя 'count()' с PHP. –

+0

Вы могли бы, но я не думаю, что это очень эффективно – Philipp

+0

И если вы хотите найти пробелы, посмотрите [здесь] (http://stackoverflow.com/questions/4340793/how-to-find-gaps-in-sequential -numbering-в-MySQL). – Rik

1

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

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

+1

Спасибо. Вместо этого я перешел на вкладку «Операции» и изменил значение auto_increment. –

0

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

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

Thanks @DarylGill –