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
SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';
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
- Im Systemtabellenbereich waren noch 106 GB vorhanden.
- Ich habe den gleichen
Table is Full
Zustand
Dies 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
Beachten 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
mysqldump --no-create-info mydb mytable > table_data.sql
SCHRITT 02
Melden Sie sich bei MySQL an und führen Sie dies aus
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
SCHRITT 03
Laden Sie die Tabelle mit dem zusätzlichen Index mit den Daten
mysql -Dmydb < table_data.sql
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 wird mytable_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
mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz
SCHRITT 02
Melden Sie sich bei MySQL an und führen Sie dies aus
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
SCHRITT 03
Laden Sie die Tabelle mit dem zusätzlichen Index mit den Daten
gzip -d < table_data.sql.gz | mysql -Dmydb
oder
gunzip < table_data.sql.gz | mysql -Dmydb
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?
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
Sehen Sie das disk quota exceeded
? Wo wird dieses Festplattenkontingent festgelegt?
Führen Sie diese Abfrage aus
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Du hast gesagt, es ist /var/lib/mysqltmp
Führen Sie dies nun im Betriebssystem aus
df -h /var/lib/mysqltmp
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 am tmpdir
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
InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.
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 :
Während der Indexerstellung werden Dateien in das temporäre Verzeichnis geschrieben ($ TMPDIR unter Unix,% TEMP% unter Windows oder der Wert der Konfigurationsvariablen --tmpdir). Jede temporäre Datei ist groß genug, um eine Spalte zu enthalten, aus der der neue Index besteht, und jede wird entfernt, sobald sie mit dem endgültigen Index zusammengeführt wird.
Aufgrund einer Einschränkung von MySQL wird die Tabelle kopiert, anstatt "Schnelle Indexerstellung" zu verwenden, wenn Sie einen Index für eine TEMPORARY TABLE erstellen. Dies wurde als MySQL Bug # 39833 gemeldet .
UPDATE 2014-06-16 13:58 EDT
[mysqld]
datadir = /mnt/cbsvolume1/var/lib/mysql
tmpdir = /mnt/cbsvolume1/var/lib/mysql
Bitte stellen Sie sicher, dass /mnt/cbsvolume1/var/lib/mysql
100G oder mehr frei sind