Tolong jangan tertipu oleh pesan kesalahan The table 'my_table' is full. Skenario langka ini sama sekali tidak ada hubungannya dengan ruang disk. Kondisi lengkap tabel ini berkaitan dengan pipa ledeng internal InnoDB.
Pertama, lihat diagram Arsitektur InnoDB ini

Harap dicatat bahwa tablespace sistem (file ibdata) hanya memiliki 128 Rollback Segments dan 1023 Rollback Slots Per Rollback Segment. Ini membatasi ukuran kapasitas kemunduran transaksi. Dengan kata lain, jika satu segmen rollback membutuhkan lebih dari 1023 slot untuk mendukung transaksi, transaksi akan mencapai table is fullkondisi itu.
Pikirkan restoran Red Lobster di New Jersey . Mungkin memiliki kapasitas 200 orang. Jika restoran penuh, barisan orang mungkin pergi ke luar untuk menunggu. Jika orang-orang di telepon menjadi tidak sabar, mereka mungkin pergi karena restoran penuh. Jelas, solusinya tidak akan membuat New Jersey lebih besar (atau mendapatkan lebih banyak ruang disk). Solusinya adalah membuat restoran Red Lobster lebih besar. Dengan begitu Anda dapat meningkatkan kapasitas tempat duduk, katakanlah, 240. Bahkan dengan itu, garis dapat terbentuk di luar jika lebih dari 240 orang memutuskan untuk datang ke Red Lobster.
Sebagai contoh, saya punya klien dengan 2TB sistem tablespace dan innodb_file_per_table dinonaktifkan. (346G untuk ibdata1, reset untuk ibdata2). Saya menjalankan kueri ini
SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';
Selanjutnya, saya mengurangi InnoDBDataIndexSpace dari jumlah filesizes untuk ibdata1 dan ibdata2. Saya mendapat dua hal yang mengejutkan saya
- Ada 106GB yang tersisa di dalam tablespace sistem.
- Saya mendapat
Table is Fullkondisi yang sama
Ini berarti bahwa 106GB digunakan untuk pipa internal InnoDB. Klien menggunakan ext3 pada saat itu.
Solusi bagi saya adalah menambahkan ibdata3. Saya membahas ini di posting lama saya. Bagaimana mengatasi "Tabel ... sudah penuh" dengan "innodb_file_per_table"?
Saya telah membahas ini di postingan lain juga
Perlu diingat bahwa kondisi ini dapat terjadi bahkan jika innodb_file_per_table diaktifkan. Bagaimana? Rollbacks dan Undo Logs adalah sumber lonjakan yang tidak terkontrol adalah pertumbuhan untuk ibdata1 .
PERTANYAAN SEBENARNYA
Karena Anda menambahkan indeks ke tabel dan mendapatkan Table is Full, tabel tersebut harus besar dan tidak dapat masuk ke dalam segmen rollback tunggal. Anda harus melakukan hal berikut:
LANGKAH 01
Dapatkan data ke dalam file dump
mysqldump --no-create-info mydb mytable > table_data.sql
LANGKAH 02
Login ke MySQL dan jalankan ini
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;
LANGKAH 03
Muat tabel dengan indeks tambahan dengan data
mysql -Dmydb < table_data.sql
Itu saja.
Lihat, masalahnya adalah bahwa ALTER TABLE akan mencoba menyuntikkan semua baris dalam tabel besar Anda sebagai satu transaksi. Menggunakan mysqldump akan memasukkan data ke dalam tabel (sekarang dengan indeks baru) ribuan baris sekaligus, tidak semua baris dalam satu transaksi.
Jangan khawatir tentang what if this doesn't work?Tabel asli akan dinamai mytable_oldjika ada sesuatu. itu bisa berfungsi sebagai cadangan. Anda dapat menjatuhkan cadangan saat Anda tahu tabel baru berfungsi untuk Anda.
Cobalah !!!
UPDATE 2014-06-16 11:13 EDT
Jika Anda khawatir tentang dump data yang lebih besar, cukup gzip saja.
Anda bisa melakukan langkah yang sama, tetapi sebagai berikut
LANGKAH 01
Dapatkan data ke dalam file dump
mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz
LANGKAH 02
Login ke MySQL dan jalankan ini
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;
LANGKAH 03
Muat tabel dengan indeks tambahan dengan data
gzip -d < table_data.sql.gz | mysql -Dmydb
atau
gunzip < table_data.sql.gz | mysql -Dmydb
UPDATE 2014-06-16 12:55 EDT
Saya hanya memikirkan aspek lain berkenaan dengan masalah ini.
Karena Anda melakukan DDL dan bukan DML, ada kemungkinan bahwa ini bukan pipa saluran internal InnoDB. Karena DDL tidak dapat mengembalikan untuk InnoDB , masalahnya harus menjadi saluran pipa eksternal. Di mana pipa eksternal ini tersumbat? Saya curiga folder temp untuk OS. Mengapa?
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
Lihat disk quota exceeded? Di mana kuota disk ini diberlakukan?
Jalankan kueri ini
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Anda mengatakan itu /var/lib/mysqltmp
Sekarang, jalankan ini di OS
df -h /var/lib/mysqltmp
Sesuatu memberi tahu saya bahwa ruang untuk /var/lib/mysqltmpkehabisan Setelah semua, Anda hanya memiliki 14G gratis. Di mata DDL (untuk membuat indeks), kemunduran terjadi, bukan pada file ibdata1, tetapi di tmpdirlokasi. Jika /var/lib/mysqltmptidak dipasang di mana saja, maka data temp sedang ditulis di partisi root. Jika /var/lib/mysqltmpdipasang di suatu tempat, maka mount itu sedang diisi dengan data baris. Dalam kedua kasus, tidak ada cukup ruang untuk menyelesaikan DDL.
Anda memiliki dua opsi di sini
PILIHAN 1
Anda juga bisa membuat disk besar (mungkin dengan 100 + GB) dan pasang /var/lib/mysqltmpdi disk besar itu.
PILIHAN 2
Saran 3 langkah saya akan tetap berfungsi, bahkan dengan ruang disk terbatas yang Anda miliki
KOMENTAR
Sayang sekali pesan kesalahan yang Anda posting mengatakan
InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.
Ini berarti OS baik-baik saja. Itu juga tidak ada nomor kesalahan terkait untuk situasi ini.
Ada hal lain yang harus Anda ketahui. Dokumentasi MySQL mengatakan bahwa Pembuatan Indeks Cepat untuk InnoDB masih masuk ke disk :
Selama pembuatan indeks, file ditulis ke direktori sementara ($ TMPDIR pada Unix,% TEMP% pada Windows, atau nilai variabel konfigurasi --tmpdir). Setiap file sementara cukup besar untuk menampung satu kolom yang membentuk indeks baru, dan masing-masing dihapus segera setelah digabungkan ke dalam indeks akhir.
Karena keterbatasan MySQL, tabel disalin, daripada menggunakan "Pembuatan Indeks Cepat" saat Anda membuat indeks pada TABEL SEMENTARA. Ini telah dilaporkan sebagai Bug MySQL # 39833 .
UPDATE 2014-06-16 13:58 EDT
[mysqld]
datadir = /mnt/cbsvolume1/var/lib/mysql
tmpdir = /mnt/cbsvolume1/var/lib/mysql
Pastikan /mnt/cbsvolume1/var/lib/mysqlmemiliki 100G atau lebih gratis