Warum springt das automatische Inkrementieren um mehr als die Anzahl der eingefügten Zeilen?

11

Ich bin sehr beunruhigt über dieses seltsame Verhalten, das ich in dem auto_incrementWert sehe, der in der bidID einer Bids-Tabelle aufgezeichnet ist, nachdem eine Masseneinfügung mit einer gespeicherten Prozedur durchgeführt wurde:

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;

Wenn der auto_incrementbidID-Wert beispielsweise zu Beginn 101 ist und ich 100 Zeilen eingefügt habe, wird der Endwert 213 anstelle von 201. Die bidIDs dieser eingefügten Zeilen werden jedoch nacheinander bis maximal 201 ausgeführt.

Nachdem Sie Folgendes überprüft haben:

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

Ich habe keine Ahnung, warum es passiert. Was könnte den Wertsprung verursachen auto increment?

Fragenüberlauf
quelle
MyISAM- oder InnoDB-Tabellen?
Cristian Porta
@CristianPorta, es ist InnoDB.
Frage Überlauf
Können Sie Ihre show variables like '%innodb_autoinc_lock_mode%';Ausgabe teilen ?
Cristian Porta
Sind Sie sicher, dass keine andere Verbindung / Aktivität mit der Tabelle zusammenhängt (Einfügen von Zeilen)?
Ypercubeᵀᴹ
1
@QuestionOverflow ein guter Ausgangspunkt: dev.mysql.com/doc/refman/5.5/en/…
Cristian Porta

Antworten:

10

Dies ist nicht ungewöhnlich und es gibt mehrere Ursachen. Manchmal liegt es an Optimierungen, die der Abfrageläufer vornimmt, um Konfliktprobleme mit der Zählerressource zu reduzieren und die Effizienz zu verbessern, wenn die betroffene Tabelle gleichzeitig aktualisiert wird. Manchmal liegt es an Transaktionen, die explizit zurückgesetzt wurden (oder implizit zurückgesetzt wurden, weil ein Fehler aufgetreten ist).

Die einzige Garantie aus einer auto_incrementSpalte (oder IDENTITYin MSSQL und den anderen Namen, nach denen das Konzept verwendet wird) ist, dass jeder Wert eindeutig und niemals kleiner als ein vorheriger ist. Sie können sich also bei der Bestellung auf die Werte verlassen, aber nicht darauf sie sollen keine Lücken haben.

Wenn Sie möchten, dass die Werte der Spalte überhaupt keine Lücken aufweisen, müssen Sie die Werte selbst verwalten, entweder in einer anderen Ebene der Geschäftslogik oder in der Datenbank über einen Trigger (achten Sie jedoch auf mögliche Leistungsprobleme mit Triggern), wenn Wenn Sie Ihre eigenen rollen, müssen Sie sich mit allen Problemen in Bezug auf Parallelität / Rollback / Bereinigung nach dem Löschen / andere Probleme auseinandersetzen, die die DB-Engines umgehen, indem sie Lücken zulassen.

David Spillett
quelle
Können Sie einige Referenzen angeben, in denen dieses Verhalten diskutiert wird?
Frage Überlauf
1
Es gibt hier, auf SO und allgemein einige Hinweise auf die Angelegenheit. Suchen Sie nach "IDENTITY-Lücken", "auto_increment-Lücken" usw., und Sie sollten genügend Diskussionen finden. Sie können Ihren DBMS-Namen hinzufügen, um die Suche spezifischer zu gestalten. Dies ist jedoch ein recht allgemeines Konzept, sodass es möglicherweise keinen wirklichen Unterschied macht, es sei denn, Sie schauen unter die Haube, wie es im Detail funktioniert.
David Spillett
4
Weitere Informationen finden Sie in den Details zu MySQL: AUTO_INCREMENT Handling in InnoDB . Dort wird Folgendes erwähnt: " Lücken in den Werten für die automatische Inkrementierung für" Masseneinfügungen " ... Bei den Sperrmodi 1 oder 2 können Lücken zwischen aufeinanderfolgenden Anweisungen auftreten, da bei Masseneinfügungen die genaue Anzahl angegeben wird Die Anzahl der für jede Anweisung erforderlichen Auto-Inkrement-Werte ist möglicherweise nicht bekannt, und eine Überschätzung ist möglich. "
Ypercubeᵀᴹ
@ypercube, danke, das ist sehr hilfreich von dir.
Frage Überlauf