UPDATE: tl; dr: Das Problem war, dass MySQL das TMPDIR
beim Erstellen von Indizes verwendet. Und mir TMPDIR
ging der Speicherplatz aus.
Original Q:
Ich versuche, einer InnoDB-Tabelle einen Index hinzuzufügen und einen zu erhalten table is full error
. Ich habe genügend Speicherplatz und die MySQL-Konfiguration hat eine Datei pro Tabelle = 1. Die Tabellendaten sind 85 GB und ich gehe davon aus, dass der Index zwischen 20 GB und 30 GB liegt und ich viel mehr Speicherplatz habe. Ich verwende auch ext3, damit ich aus Sicht des Betriebssystems keine Probleme mit der Dateigrößenbeschränkung habe.
Der protokollierte Fehler sieht folgendermaßen aus:
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
Was verursacht dies und wie kann ich es beheben?
Die Create-Tabelle:
`CREATE TABLE `my_table` (
`uid_from` bigint(11) NOT NULL,
`uid_to` bigint(11) NOT NULL,
`counter` int(11) NOT NULL,
`updated` date NOT NULL,
PRIMARY KEY (`uid_to`,`uid_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8`
Wie ist die Daten ist 87,4 GB und ich schätze, es gibt etwa 1,5 Milliarden Zeilen.
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Variable_name Value
tmpdir /tmp
[root@web ~]# df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 40G 24G 14G 64% /
Antworten:
Bitte lassen Sie sich von der Fehlermeldung nicht täuschen
The table 'my_table' is full
. Dieses seltene Szenario hat absolut nichts mit Speicherplatz zu tun. Dieser vollständige Zustand der Tabelle hat mit der internen Installation von InnoDB zu tun.Schauen Sie sich zunächst dieses Diagramm der InnoDB-Architektur an
Bitte beachten Sie, dass der Systemtabellenbereich (die Datei ibdata) nur 128 Rollback-Segmente und 1023 Rollback-Slots pro Rollback-Segment enthält. Dadurch wird die Größe der Rollback-Kapazität einer Transaktion begrenzt. Mit anderen Worten, wenn ein einzelnes Rollback-Segment mehr als 1023 Slots benötigt, um eine Transaktion zu unterstützen, trifft die Transaktion diese
table is full
Bedingung.Denken Sie an das Restaurant Red Lobster in New Jersey . Es kann eine Kapazität von 200 Personen haben. Wenn das Restaurant voll ist, kann eine Reihe von Leuten nach draußen gehen, um zu warten. Wenn die Leute in der Leitung ungeduldig werden, können sie gehen, weil das Restaurant voll ist. Offensichtlich wäre die Lösung nicht, New Jersey größer zu machen (oder mehr Speicherplatz zu bekommen). Die Lösung wäre, das Red Lobster Restaurant größer zu machen. Auf diese Weise können Sie die Sitzplatzkapazität auf beispielsweise 240 erhöhen. Trotzdem kann sich draußen eine Linie bilden, wenn mehr als 240 Personen zu Red Lobster kommen.
Um Ihnen ein Beispiel zu geben, ich hatte einen Client mit 2 TB Systemtabellenbereich und innodb_file_per_table war deaktiviert. (346G für ibdata1, das Zurücksetzen für ibdata2). Ich habe diese Abfrage ausgeführt
Als nächstes habe ich InnoDBDataIndexSpace von der Summe der Dateigrößen für ibdata1 und ibdata2 abgezogen. Ich habe zwei Dinge, die mich schockierten
Table is Full
ZustandDies bedeutet, dass die 106 GB für die interne Installation von InnoDB verwendet wurden. Der Client verwendete zu diesem Zeitpunkt ext3.
Die Lösung für mich war, ibdata3 hinzuzufügen. Ich habe dies in meinem alten Beitrag besprochen. Wie löse ich "Die Tabelle ... ist voll" mit "innodb_file_per_table"?
Ich habe dies auch in anderen Beiträgen besprochen
Mar 31, 2014
: Das MySQL-Verzeichnis wächst nach einer Abfrage, die aufgrund einer vollen Tabelle fehlgeschlagen ist, auf 246 GBNov 25, 2011
: FEHLER 1114 (HY000) in Zeile 6308 in Datei & Die Tabelle user_analysis ist vollBeachten Sie, dass diese Bedingung auch dann auftreten kann, wenn innodb_file_per_table aktiviert wurde. Wie? Rollbacks und Rückgängig-Protokolle sind die Ursache für unkontrollierte Spitzen. Dies ist das Wachstum von ibdata1 .
IHRE TATSÄCHLICHE FRAGE
Da Sie einer Tabelle einen Index hinzufügen und abrufen
Table is Full
, muss die Tabelle sehr groß sein und darf nicht in ein einzelnes Rollback-Segment passen. Sie müssen Folgendes tun:SCHRITT 01
Holen Sie sich die Daten in eine Dump-Datei
SCHRITT 02
Melden Sie sich bei MySQL an und führen Sie dies aus
SCHRITT 03
Laden Sie die Tabelle mit dem zusätzlichen Index mit den Daten
Das ist alles.
Das Problem ist, dass die ALTER TABLE versucht, alle Zeilen in Ihrer riesigen Tabelle als einzelne Transaktion einzufügen. Wenn Sie mysqldump verwenden, werden die Daten Tausende von Zeilen gleichzeitig in die Tabelle (jetzt mit einem neuen Index) eingefügt, nicht alle Zeilen in einer einzelnen Transaktion.
Keine Sorge
what if this doesn't work?
Die Originaltabelle wirdmytable_old
im Falle von irgendetwas benannt. Es kann als Backup dienen. Sie können die Sicherung löschen, wenn Sie wissen, dass die neue Tabelle für Sie funktioniert.Versuche es !!!
UPDATE 2014-06-16 11:13 EDT
Wenn Sie sich Sorgen über den Speicherauszug der Daten machen, der größer ist, gzipen Sie ihn einfach.
Sie können die gleichen Schritte ausführen, jedoch wie folgt
SCHRITT 01
Holen Sie sich die Daten in eine Dump-Datei
SCHRITT 02
Melden Sie sich bei MySQL an und führen Sie dies aus
SCHRITT 03
Laden Sie die Tabelle mit dem zusätzlichen Index mit den Daten
oder
UPDATE 2014-06-16 12:55 EDT
Ich habe gerade an einen anderen Aspekt in Bezug auf dieses Thema gedacht.
Da Sie DDL und nicht DML verwenden, ist es möglich, dass dies keine InnoDB-interne Installation ist. Da DDL für InnoDB kein Rollback durchführen kann , muss das Problem eine externe Installation sein. Wo wird diese externe Installation verstopft? Ich vermute den temporären Ordner für das Betriebssystem. Warum?
Sehen Sie das
disk quota exceeded
? Wo wird dieses Festplattenkontingent festgelegt?Führen Sie diese Abfrage aus
Du hast gesagt, es ist
/var/lib/mysqltmp
Führen Sie dies nun im Betriebssystem aus
Etwas sagt mir, dass der Speicherplatz für knapp
/var/lib/mysqltmp
wurde. Immerhin haben Sie nur 14G frei. In den Augen der DDL (um den Index zu erstellen) kam es zu einem Rollback, nicht in der Datei ibdata1, sondern amtmpdir
Speicherort. Wenn/var/lib/mysqltmp
es nirgendwo gemountet ist, werden die temporären Daten in die Root-Partition geschrieben. Wenn/var/lib/mysqltmp
es irgendwo gemountet ist, wird dieses Mount mit Zeilendaten gefüllt. In beiden Fällen ist nicht genügend Platz vorhanden, um die DDL abzuschließen.Sie haben hier zwei Möglichkeiten
OPTION 1
Sie können auch eine große Festplatte (möglicherweise mit mehr als 100 GB) erstellen und
/var/lib/mysqltmp
auf dieser großen Festplatte bereitstellen.OPTION 2
Meine 3-Schritt-Vorschläge sollten auch bei begrenztem Speicherplatz funktionieren
KOMMENTAR
Es ist eine Schande, dass die von Ihnen gepostete Fehlermeldung besagt
Dies bedeutet, dass das Betriebssystem in Ordnung ist. Es gibt auch keine zugehörige Fehlernummer für diese Situation.
Es gibt noch eine andere Sache, die Sie wissen sollten. Die MySQL-Dokumentation besagt, dass die schnelle Indexerstellung für InnoDB weiterhin auf der Festplatte gespeichert wird :
UPDATE 2014-06-16 13:58 EDT
Bitte stellen Sie sicher, dass
/mnt/cbsvolume1/var/lib/mysql
100G oder mehr frei sindquelle