Правильно ли делать SELECT MAX (id) и т. Д. Для нахождения последней вставленной строки? - PullRequest
10 голосов
/ 01 декабря 2011

Я просматривал модуль Drupal, когда нашел этот шаблон для получения идентификатора последней вставленной строки:

SELECT MAX(id) FROM ... WHERE ...

, где id - это поле, работающее обычным способом автоинкремента.

Это концептуально правильно делать?Есть ли ситуации, когда этот шаблон не работает в среде MySQL / PostgreSQL?

Редактировать:

Спасибо за отличные комментарии и ответы!

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

Ответы [ 8 ]

12 голосов
/ 01 декабря 2011

Это кажется субъективным, но я бы сказал, нет, это не концептуально правильно, потому что:

  • вы хотите самую последнюю вставленную строку
  • но ваш запрос смотрит на максимальное id значение

Да, существует некоторая связь между максимальным идентификатором и последней вставкой, но учтите следующее:

  • что если последняя вставленная строка была удалена?

Ответ на MySQL: вы получите разные результаты. Обратите внимание, что для этого не требуется даже многопоточность или несколько процессов. Это потому, что это две разные вещи (которые по общему признанию могут часто давать одинаковые результаты).

select max(id) from <tablename>

против

select last_insert_id()

(Угадай, кто из них прав.)


@ Демс указала, что ОП неоднозначна. Я уточню свой главный вопрос:

Мы говорим о трех разных видах информации:

  • максимум id значение
  • id последней вставленной строки, относящейся к сеансу
  • id последней строки, вставленной в таблицу (независимо от сеанса)

Опасность в том, что иногда запрос одного дает правильный ответ другому - , но не всегда .

5 голосов
/ 01 декабря 2011

select max (id) гарантирует получение только записи с самым высоким ID.это не обязательно последняя запись, вставленная в таблицу.Помните, что операции с БД могут выполняться параллельно.Вы можете вставить запись и получить ID # 5.Но к тому моменту, когда вы приступите к выполнению select MAX(id), кто-то еще мог вставить другую запись, и теперь максимум действительно # 6.

Кроме того, вы не можете использовать его, чтобы предсказать, чтоследующий назначенный идентификатор может быть.Рассмотрим случай, когда в транзакции выполняются некоторые вставки.Последняя зафиксированная запись в БД снова № 5, затем выполняются 3 вставки (№ 6, № 7, № 8), а затем они откатываются.Следующей вставкой, которая будет выполнена, на самом деле будет # 9, а не # 6 снова - mysql не перезапускает идентификационные номера из неудачных транзакций.И нет никакой гарантии, что ВЫ тоже получите # 9 - какой-то другой сеанс мог бы выполнить вставку, прежде чем приступить к нему, поэтому ваша четвертая вставка может быть # 10 или # 10 000 000 вместо этого.

2 голосов
/ 01 декабря 2011

В MySQL вы можете просто использовать last_insert_id (), который более гарантированно работает.

2 голосов
/ 01 декабря 2011
1 голос
/ 01 декабря 2011

Прочитайте это: Директива 595

Epic не может доверять MAX (id), он терпит неудачу большое время.

1 голос
/ 01 декабря 2011

Это зависит от предложения WHERE и от того, как приложение вставляет в эту таблицу. SELECT max(ID) FROM table всегда будет возвращать самый большой идентификатор во время выполнения запроса. Предполагая, что ID является первичным ключом auto_increment, он вернет самую последнюю строку. Однако в многопоточных средах, таких как веб-серверы, это может быть не тот идентификатор, который вы ожидаете, поскольку другой процесс также может быть вставлен в эту таблицу. Например, если ваш PHP-код вставляется в таблицу, select max(id) ожидает получить только что вставленную строку, это может не сработать, поскольку другой процесс мог вставить другую строку после того, как вы сделали вставку и до того, как вы сделали select max.

Если идентификатор является первичным ключом auto_increment (mysql), то MySql last_insert_id() или PHP mysql_insert_id() обычно является лучшим выбором. Но опять же, не зная таблицы, предложения WHERE или того, что Drupal ожидает от этого запроса, невозможно сказать, «делает ли Drupal« неправильно ».

0 голосов
/ 01 декабря 2011

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

0 голосов
/ 01 декабря 2011

PostgreSQL вам приходится иметь дело с sequences, поэтому все зависит от того, как его настроить

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...