Wir haben eine MySQL-Tabelle mit einem automatisch inkrementierenden Feld, das als INT (11) festgelegt ist. In dieser Tabelle wird eine Liste der Jobs gespeichert, die in einer Anwendung ausgeführt werden. Zu jedem Zeitpunkt während der Lebensdauer der Anwendung kann die Tabelle Tausende von Einträgen enthalten oder vollständig leer sein (dh alles ist beendet).
Das Feld ist für nichts anderes fremdverschlüsselt.
Das Auto-Inkrement scheint sich zufällig auf Null zurückzusetzen, obwohl es uns noch nie gelungen ist, das Zurücksetzen einzufangen.
Das Problem wird offensichtlich, weil das Auto-Inkrement-Feld auf etwa 600.000 Datensätze ansteigt und eine Weile später das Auto-Inkrement-Feld in den niedrigen 1000er-Werten zu laufen scheint.
Es ist fast so, als würde sich das Auto-Inkrement von selbst zurücksetzen, wenn die Tabelle leer ist.
Ist dies möglich und wenn ja, wie schalte ich es aus oder ändere die Art und Weise, in der es zurückgesetzt wird?
Wenn dies nicht der Fall ist, hat jemand eine Erklärung, warum dies möglicherweise der Fall ist?
Vielen Dank!
quelle
Antworten:
http://dev.mysql.com/doc/refman/4.1/de/innodb-auto-increment-handling.html
Aus diesem Grund geschieht beim Neustart des Dienstes (oder Servers) Folgendes:
Nachdem der MySQL-Dienst gestartet wurde, hat er im Klartext keine Ahnung, wie hoch der Auto-Inkrement-Wert für Ihre Tabelle sein sollte. Wenn Sie also zum ersten Mal eine Zeile einfügen, wird der Maximalwert des Felds ermittelt, das die automatische Inkrementierung verwendet, 1 zu diesem Wert hinzugefügt und der resultierende Wert verwendet. Wenn keine Zeilen vorhanden sind, wird mit 1 begonnen.
Dies war ein Problem für uns, da wir die Tabelle und die automatische Inkrementierungsfunktion von mysql verwendeten, um IDs in einer Umgebung mit mehreren Threads sauber zu verwalten, in der Benutzer zu einer Zahlungswebsite eines Drittanbieters weitergeleitet wurden. Daher mussten wir sicherstellen, dass die ID, die der Dritte erhalten und an uns zurückgesandt hat, eindeutig ist und dies auch bleibt (und natürlich besteht die Möglichkeit, dass der Benutzer die Transaktion nach der Weiterleitung storniert).
Also haben wir eine Zeile erstellt, den generierten Wert für die automatische Inkrementierung abgerufen, die Zeile gelöscht, um die Tabelle sauber zu halten, und den Wert an die Zahlungssite weitergeleitet. Am Ende haben wir Folgendes getan, um das Problem zu beheben, wie InnoDB AI-Werte verarbeitet:
Auf diese Weise wird immer die letzte als Zeile in der Tabelle generierte Transaktions-ID beibehalten, ohne dass die Tabelle unnötig in die Luft gesprengt wird.
Hoffe, das hilft allen anderen, die darauf stoßen könnten.
Bearbeiten (2018-04-18) :
Wie Finesse weiter unten erwähnte, wurde das Verhalten in MySQL 8.0+ geändert.
https://dev.mysql.com/worklog/task/?id=6204
Der Wortlaut in diesem Worklog ist bestenfalls fehlerhaft, es scheint jedoch, dass InnoDB in diesen neueren Versionen nun persistente Autoinc-Werte über Neustarts hinweg unterstützt.
-Gremio
quelle
Wir haben dieses Problem festgestellt und festgestellt, dass der Wert für die automatische Inkrementierung ebenfalls zurückgesetzt wurde, als die Optimierungstabelle für eine leere Tabelle ausgeführt wurde. Siehe diesen MySQL-Fehlerbericht .
Als Problemumgehung können Sie Folgendes tun:
Anstelle von
OPTIMIZE TABLE
.Es sieht so aus, als ob MySQL dies intern tut (natürlich ohne den Wert für das automatische Inkrementieren festzulegen).
quelle
Nur ein Schuss in die Dunkelheit - wenn die Anwendung a verwendet
TRUNCATE TABLE
, um die Tabelle nach Abschluss der Verarbeitung zu leeren, wird das Auto-Inkrement-Feld zurückgesetzt. Hier ist eine kurze Diskussion zu dieser Frage. Dieser Link erwähnt zwar, dass InnoDB auto_increments auf einem Trunc nicht zurücksetzt, dies wurde jedoch als Fehler gemeldet und vor einigen Jahren behoben.Unter der Annahme, dass meine Vermutung richtig ist, können Sie vom Abschneiden zum Löschen wechseln, um das Problem zu beheben.
quelle
Nur ein explizites Zurücksetzen dieses Wertes oder ein Löschen / erneutes Erstellen dieses Feldes oder eine ähnliche gewaltsame Operation sollte einen auto_increment-Zähler jemals zurücksetzen. (Die TRUNCATE war eine wirklich gute Theorie.) Es scheint unmöglich, dass Sie plötzlich ein 32-Bit-INT einbinden, wenn der letzte Wert, den Sie sehen, nur 600 KB beträgt. Es sollte definitiv nicht zurückgesetzt werden, nur weil der Tisch leer ist. Sie haben entweder einen Mysql-Fehler oder etwas in Ihrem PHP-Code. Oder der Typ in der Kabine nebenan spielt dir einen Streich.
Sie können das Debuggen durchführen, indem Sie das Binärprotokoll aktivieren , da es Anweisungen wie die folgende enthält:
Dann können Sie zumindest jedes Detail dessen sehen, was mit dieser Tabelle passiert, auch bevor der Zähler zurückgesetzt wird.
quelle
ALTER TABLE table_name ENGINE = MyISAM
Arbeitet für mich. Unser Tisch wird immer sehr klein gehalten, sodass InnoDB nicht benötigt wird.
quelle
InnoDB speichert keinen Auto-Inkrement-Wert auf der Festplatte und vergisst ihn daher, wenn der MySQL-Server heruntergefahren wird. Wenn der MySQL wieder gestartet wird, stellt die InnoDB - Engine diese Weise wird die Autoinkrement - Wert:
SELECT (MAX(id) + 1) AS auto_increment FROM table
. Dies ist ein Fehler , der in MySQL Version 8.0 behoben ist .Ändern Sie die Tabellen-Engine, um das Problem zu beheben:
Oder aktualisieren Sie den MySQL-Server bei Veröffentlichung auf Version 8.0.
quelle