MySQL столбец auto_increment увеличивается на случайное значение - PullRequest
6 голосов
/ 19 апреля 2011

Сегодня я столкнулся с одной из самых странных вещей с MySQL, которую я видел.У меня есть тривиальная таблица:

CREATE TABLE `features`
(
  `feature_id` mediumint(6) unsigned NOT NULL AUTO_INCREMENT,
  `feature_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
  PRIMARY KEY (`feature_id`),
  UNIQUE KEY `feature_name_key` (`feature_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Я вставляю данные в библиотеку Java и mysql-connector-java-5.1.15.Данные в имя_функции могут дублироваться, и я хочу только уникальные значения.Я могу использовать INSERT IGNORE, но если данные слишком длинные, я могу пропустить их, поэтому я использую это:

pstmt = conn.prepareStatement( 
        "INSERT INTO features (feature_name) VALUES (?)" );

for ( String featureName: data4db.keySet() )
{
    pstmt.setString(1, featureName );

    try
    {
        pstmt.executeUpdate();
    }
    catch ( SQLException se )
    {
        if ( se.getErrorCode() == 1062 ) // duplicate entry
        {
            continue; // ignore
        }

        throw se; // do not ignore anything else
    }
}

После того, как данные были вставлены в БД, я заметил, что были некоторые проблемы, которых я недаже ожидал.В приведенной выше таблице примерно 4000 записей, и это нормально.Единственная проблема заключается в том, что некоторые данные не могут быть вставлены из-за дублирования первичного ключа, поэтому я посмотрел, как выглядят значения auto inc для этой таблицы.Оказывается, что для большинства данных идентификатор соседних строк был увеличен на 1, как и ожидалось.По причине, которую я не знаю, иногда feature_id был увеличен на 3, 5, 1000, 100000 - совершенно случайное значение.Следовательно, я «исчерпал место в этой таблице», так как его нельзя было вставить, когда id достиг максимального значения для среднего целого.

Как это может произойти?Кто-нибудь сталкивался с чем-то подобным?Стоит сказать, что в эту таблицу была записана только одна программа с одним потоком.У меня есть еще одна таблица, почти идентичная - ширина столбца и имена разные.Для этого есть похожая проблема.

Кстати - еще немного данных:

mysql> show global variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.01 sec)

mysql> show global variables like 'ver%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| version                 | 5.5.10                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86                          |
| version_compile_os      | Win32                        |
+-------------------------+------------------------------+

Спасибо за любые подсказки заранее.

Ответы [ 2 ]

11 голосов
/ 19 апреля 2011

Это нормальное поведение MySQL. Произошло следующее: вы вставили данные до ключа auto_increment 3, затем вы получили дубликат ключа, поскольку ваш имя_функции_ключ определено уникально. Дело в том, что MySQL будет «тратить» целое число 4 и перейдет к следующему, он не будет повторно использовать целые числа, которые не удалось записать из-за ограничения ключа.

Если у вас было что-то вроде этого:

PK | feature_name_key
1 | key1
2 | key2
3 | key3
4 | key1 (fails due to constraint, 4 is not going to be used for next successful insertion, hence the gaps in your primary key)

тогда вы теряете целые числа, доступные для первичного ключа / auto_increment. Пересмотрите свою стратегию, вставляя или создавая таблицу для хранения ваших данных.

0 голосов
/ 19 апреля 2011

Между вашими вставками вы удалили строки?MySQL может просто запоминать счетчик автоинкрементов.

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