Чому автоматичний приріст скаче більше, ніж кількість вставлених рядків?


11

Мене дуже турбує ця дивна поведінка, яку я бачу у auto_incrementзначенні, записаному в bidID таблиці ставок після виконання масової вставки за допомогою збереженої процедури:

INSERT INTO Bids (itemID, buyerID, bidPrice)
 SELECT itemID, rand_id(sellerID, user_last_id), FLOOR((1 + RAND())*askPrice)
 FROM Items
 WHERE closing BETWEEN NOW() AND NOW() + INTERVAL 1 WEEK ORDER BY RAND() LIMIT total_rows;

Наприклад, якщо auto_incrementзначення bidID на початку становить 101, а я вставив 100 рядків, кінцеве значення стає 213 замість 201. Однак bidID цих вставлених рядків працює послідовно до максимуму 201.

Перевіривши наступне,

SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+

Я поняття не маю, чому це відбувається. Що може спричинити стрибок auto incrementвартості?


Таблиці MyISAM або InnoDB?
Крістіан Порта

@ CristianPorta, це InnoDB.
Переповнення питання

Чи можете ви поділитися своїм show variables like '%innodb_autoinc_lock_mode%';результатом?
Крістіан Порта

Ви впевнені, що немає іншого зв’язку / активності, пов’язаної з таблицею (вставляючи рядки)?
ypercubeᵀᴹ

1
@QuestionOverflow хороший вихідний пункт: dev.mysql.com/doc/refman/5.5/en/…
Крістіан Порта

Відповіді:


10

Це не незвично і є кілька причин. Іноді це пов’язано з оптимізаціями, які виконує запит, щоб зменшити проблеми суперечок із лічильником ресурсу, підвищивши ефективність, коли в таблиці впливають одночасні оновлення. Іноді це пов'язано з транзакціями, які явно повернули назад (або неявно повернули назад через помилку).

Єдині гарантії auto_incrementстовпця (або IDENTITYв MSSQL, а інші назви, з якими іде концепція), - це те, що кожне значення буде унікальним і ніколи не меншим, ніж попереднє: таким чином, ви можете розраховувати на значення для замовлення, але не можете покладатися на вони не мають прогалин.

Якщо вам потрібні значення стовпця, щоб не було прогалин, вам потрібно буде керувати значеннями самостійно, або в іншому шарі бізнес-логіки, або в БД через тригер (будьте обережні щодо можливих проблем з ефективністю за допомогою тригерів), звичайно, якщо якщо ви робите свій власний, вам доведеться боротися з усіма проблемами concurrency / rollback / cleanup-after-delete / іншими проблемами, з якими обробляються двигуни БД, дозволяючи прогалини).


Чи можете ви надати кілька посилань, де обговорюється така поведінка?
Переповнення питання

1
Тут є досить багато посилань на цю проблему, на SO та загалом. Шукайте "прогалини в ідентичності", "прогалини в автоматичному збільшенні" тощо, і вам слід знайти багато дискусій. Ви можете додати своє ім'я СУБД, щоб зробити пошук більш конкретним, хоча це цілком загальна концепція, яка може не мати ніяких реальних змін, якщо ви не шукаєте під кришкою, як вона детально працює.
Девід Спіллетт

4
Перегляньте деталі для MySQL: AUTO_INCREMENT Обробка в InnoDB , де вона згадує: " Пропуски в значеннях автоматичного збільшення для" масових вставок " ... У режимах блокування 1 або 2 можуть виникати прогалини між послідовними операторами, тому що для масових вставок точне число значень автоматичного збільшення, необхідних для кожного оператора, може бути невідомим, і завищення можливе. "
ypercubeᵀᴹ

@ypercube, дякую, це вам найбільше допомагає.
Переповнення запитань

Також дивіться bugs.mysql.com/bug.php?id=34696 .
трсс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.