MySQL. Нахождение “дыр” в нумерации

После удаления записи в таблице базы данных, автоинкрементное id освобождается и уже никогда не будет использовано.

+-- --+-------------------+------------+-------------+
| id  | name              | date       | origin      |
+---- +-------------------+------------+-------------+
| 1   | housefly          | 2001-09-10 | kitchen     |
| 3   | grasshopper       | 2001-09-10 | front yard  |
| 4   | stink bug         | 2001-09-10 | front yard  |
| 5   | cabbage butterfly | 2001-09-10 | garden      |
| 6   | ant               | 2001-09-10 | back yard   |
| 9   | cricket           | 2001-09-11 | basement    |
| 10  | moth              | 2001-09-14 | windowsill  |
+----+--------------------+------------+-------------+

Это сделано специально для обеспечения уникальности операций. Например, при решении вопроса синхронизации в распределённых базах данных.

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

Причины, по которым стремятся к повторному упорядочиванию:

И все же…

Как найти первую отсутствующую запись?

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

Нашел такое решение:

SELECT (`table`.`id`+1) as `empty_id`
  FROM `table`
 WHERE (
         SELECT 1
           FROM `table` as `st`
          WHERE `st`.`id` = (`table`.`id` + 1)
       ) IS NULL
ORDER BY `table`.`id`
LIMIT 1

:warning: Но следует помнить, что при большом количестве одновременных запросов в БД может получиться накладка, если два процесса получат один и тот же empty_id.

Обсуждение темы на :habr: