MySQL Endeksi oluşturma işlemi başarısız oluyor


10

GÜNCELLEME: tl; dr: Sorun MySQL'in TMPDIRdizin oluştururken kullanmasıydı . Ve TMPDIRdisk alanım biten bendim.

Orijinal S:

Bir InnoDB tabloya bir dizin eklemek çalışıyorum ve bir elde table is full error. Yeterli disk alanım var ve MySQL yapılandırması tablo başına = 1 dosyaya sahip. Tablo verileri 85GB ve endeksin 20GB - 30GB civarında olacağını ve bundan çok daha fazla disk alanım olduğunu varsayıyorum. Ben de ext3 kullanıyorum bu yüzden OS açısından dosya boyutu sınırı ile ilgili herhangi bir sorun hissetmiyorum.

Günlüğe kaydedilen hata şöyle görünür:

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

Buna neden olan nedir ve nasıl çözebilirim?

Tablo oluştur:

`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`

Veriler 87.4GB gibi ve tahminen 1.5B civarında satır var.

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% /

1
"InnoDB: İşletim sisteminizin ve dosya sisteminizin bu boyuttaki dosyaları desteklediğini kontrol edin. InnoDB: Diskin dolu olmadığını veya disk kotasının aşıldığını da kontrol edin." - kontrol ettin mi? Ext2 mi kullanıyorsunuz? ext3? xfs? Kullanıcı için kotaları kontrol ettiniz mi?
Philᵀᴹ

@Phil İkisini de kontrol etti. Ext3 kullanıyorum ve disk alanı ile ilgili bir sorun yok neredeyse pozitifim. Hunch, bir günlüğün sınırına veya başka bir şeye ulaşmasıyla ilgili bir şey var, ancak gerçekten nasıl doğrulanacağı ve düzeltileceği hakkında hiçbir fikrim yok.
Noam

Acaba "(birleştirme)" dosyası nedir?
akuzminsky

@akuzminsky hmm Hiçbir fikrim yok. Sadece PHPMyAdmin'den yeni bir dizin oluşturma çalıştırdım.
Noam

TMPDIR için +1, sunucumda da sorun vardı.
Chad

Yanıtlar:


8

Lütfen hata mesajına aldanmayın The table 'my_table' is full. Bu nadir senaryonun disk alanı ile hiçbir ilgisi yoktur. Bu tablonun tam koşulu InnoDB'nin iç tesisatıyla ilgilidir.

İlk olarak, InnoDB Mimarisinin bu şemasına bir göz atın

InnoDB Mimarisi

Sistem tablo alanında (ibdata dosyası) yalnızca 128 Geri Alma Segmenti ve Geri Alma Segmenti başına 1023 Geri Alma Yuvası bulunduğunu unutmayın. Bu, bir işlemin geri alma kapasitesinin boyutunu sınırlar. Başka bir deyişle, tek bir geri alma segmenti bir işlemi desteklemek için 1023'ten fazla yuvaya ihtiyaç duyarsa, işlem bu table is fullkoşula çarpar.

New Jersey restoranı Red Lobster düşünün . 200 kişi kapasitelidir. Restoran doluysa, bir dizi insan beklemek için dışarı çıkabilir. Hatta insanlar sabırsızlanırsa, restoran dolu olduğu için ayrılabilirler. Açıkçası, çözüm New Jersey'i büyütmek (veya daha fazla disk alanı elde etmek) değildir. Çözüm Red Lobster restoranını büyütmek olacaktır. Bu şekilde oturma kapasitesini 240'a çıkarabilirsiniz. Bununla birlikte, 240'tan fazla insan Red Lobster'a gelmeye karar verirse dışarıda bir çizgi oluşabilir.

Sadece bir örnek vermek gerekirse, 2TB sistem tablo alanı olan bir istemci vardı ve innodb_file_per_table devre dışı bırakıldı. (İbdata1 için 346G, ibdata2 için sıfırlama). Bu sorguyu çalıştırdım

SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';

Daha sonra ibnota1 ve ibdata2 için dosya boyutlarının toplamından InnoDBDataIndexSpace öğesini çıkardım. Beni şok eden iki şeyim var

  • Sistem tablo alanının içinde 106 GB kaldı.
  • Bende aynı Table is Fulldurum var

Bu 106GB'ın InnoDB'nin iç tesisatında kullanıldığı anlamına geliyor. İstemci o zaman ext3 kullanıyordu.

Benim için çözüm ibdata3 eklemekti. Ben eski yazıma bu tartıştım "tablo ... dolu" "innodb_file_per_table" ile nasıl çözülür?

Bunu diğer yazılarda da tartıştım

İnnodb_file_per_table etkinleştirilmiş olsa bile bu durumun olabileceğini unutmayın. Nasıl? Geri dönüşler ve Geri Al Günlükleri, kontrolsüz ani kaynakların ibdata1 için büyümesidir .

GERÇEK SORU

Bir tabloya dizin ekleyip aldığınızdan Table is Full, tablo çok büyük olmalı ve tek bir geri alma segmentine sığmayacaktır. Aşağıdakileri yapmanız gerekir:

ADIM 01

Verileri bir döküm dosyasına alın

mysqldump --no-create-info mydb mytable > table_data.sql

ADIM 02

MySQL'e giriş yapın ve bunu çalıştırın

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;

ADIM 03

Ek indeks içeren tabloyu verilerle yükleyin

mysql -Dmydb < table_data.sql

Bu kadar.

Sorun, ALTER TABLE'ın büyük tablonuzdaki tüm satırları tek bir işlem olarak enjekte etmeye çalışacağıdır. Mysqldump kullanarak, verileri tek bir işlemdeki tüm satırlara değil, aynı anda binlerce satıra (şimdi yeni bir dizinle) tabloya ekleyeceksiniz.

Endişelenme what if this doesn't work?Orijinal tablo mytable_oldherhangi bir şey olması durumunda adlandırılacaktır . yedek olarak kullanılabilir. Yeni tablonun sizin için çalıştığını bildiğinizde yedeklemeyi bırakabilirsiniz.

Bir şans ver !!!

GÜNCELLEME 2014-06-16 11:13 EDT

Verilerin dökümünün daha büyük olması konusunda endişeleniyorsanız, sadece gzip edin.

Aynı adımları uygulayabilirsiniz, ancak aşağıdaki gibi

ADIM 01

Verileri bir döküm dosyasına alın

mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz

ADIM 02

MySQL'e giriş yapın ve bunu çalıştırın

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;

ADIM 03

Ek indeks içeren tabloyu verilerle yükleyin

gzip -d < table_data.sql.gz | mysql -Dmydb

veya

gunzip < table_data.sql.gz | mysql -Dmydb

GÜNCELLEME 2014-06-16 12:55 EDT

Ben sadece bu konuda başka bir yönü düşündüm.

DML yerine DDL yaptığınız için, bunun InnoDB iç tesisat olmaması mümkündür. Yana DDL InnoDB için geri alma edemez , konu harici tesisat olmak zorunda. Bu harici tesisat nerede tıkanıyor? İşletim sisteminin geçici klasöründen şüpheleniyorum. Neden?

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

Gördün disk quota exceededmü? Bu disk kotası nereye uygulanıyor?

Bu sorguyu çalıştır

SHOW GLOBAL VARIABLES LIKE 'tmpdir';

Dedin ki /var/lib/mysqltmp

Şimdi bunu işletim sisteminde çalıştırın

df -h /var/lib/mysqltmp

Bir şey bana alanın tükendiğini söylüyor /var/lib/mysqltmpSonuçta, sadece 14G boş alanınız var. DDL'nin gözünde (dizini oluşturmak için) ibdata1 dosyasında değil, tmpdirkonumda bir geri alma oldu . Eğer /var/lib/mysqltmpherhangi bir yerde monte edilmediği, daha sonra geçici veri kök bölümü ile yazılmış ediliyor. Bir /var/lib/mysqltmpyere monte edilirse , o montaj satır verileri ile doldurulmaktadır. Her iki durumda da DDL'yi tamamlamak için yeterli alan yoktur.

Burada iki seçeneğiniz var

SEÇENEK 1

Ayrıca büyük bir disk (belki 100 + GB ile) oluşturabilir ve /var/lib/mysqltmpbu büyük diske takabilirsiniz .

SEÇENEK 2

3 adımlı önerilerim, sahip olduğunuz sınırlı disk alanında bile çalışmaya devam etmeli

YORUM

Gönderdiğiniz hata mesajının yazdığı bir utanç

InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.

Bu, işletim sisteminin iyi olduğu anlamına gelir. Ayrıca, bu durum için ilişkili bir hata numarası yoktur.

Bilmeniz gereken başka bir şey daha var. MySQL Belgeleri, InnoDB için Hızlı Dizin Oluşturmanın hala diske gittiğini söylüyor :

Dizin oluşturma sırasında dosyalar geçici dizine yazılır (Unix'te $ TMPDIR, Windows'ta% TEMP% veya --tmpdir yapılandırma değişkeninin değeri). Her geçici dosya, yeni dizini oluşturan bir sütunu tutacak kadar büyüktür ve her biri son dizine birleştirilir getirilmez kaldırılır.

MySQL sınırlaması nedeniyle, GEÇİCİ TABLO'da bir dizin oluşturduğunuzda tablo "Hızlı Dizin Oluşturma" kullanmak yerine kopyalanır. Bu MySQL Hata # 39833 olarak bildirildi .

GÜNCELLEME 2014-06-16 13:58 EDT

[mysqld]
datadir                         = /mnt/cbsvolume1/var/lib/mysql
tmpdir                          = /mnt/cbsvolume1/var/lib/mysql

/mnt/cbsvolume1/var/lib/mysql100G veya daha fazla ücretsiz olduğundan emin olun


Tabloyu dökümünden ilk etapta oluşturmak haftalar sürdü (85GB veri). Bunu tekrar yapmaktan başka bir yol var mı? Tabloyu bölümlendirmenizi tavsiye eder misiniz?
Noam

Dizin eklemek için ALTER TABLE yine de her şeyi tek bir işlemde yüklemeye çalışacağından bölümleme yardımcı olmaz. Unutmayın, disk alanı ile değil InnoDB Mimarisi ile savaşıyorsunuz. Cevabım bu durumda size yardımcı olmalıdır çünkü mysqldump, INSERT başına birkaç bin satır enjekte eder, bir geri alma olasılığı olan bir geçici tabloya bir ya hep ya hiç ekleme değil.
RolandoMySQLDBA

Ancak bu tabloyu oluşturmak (tekrar) sonsuza kadar sürecektir. Geri alma seçeneğini devre dışı bırakırken bir oluşturma dizini çalıştırmanın herhangi bir yolu var mı?
Noam

Dizin oluşturmak DML değil DDL'dir. DDL davranışını değiştiremezsiniz. Bu yüzden yazımda DML teknikleri kullanılıyor.
RolandoMySQLDBA

BTW masanın kaç satırı var ???
RolandoMySQLDBA
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.