"Mysql Satır boyutu çok büyük" için sınırı değiştirin


106

Limiti nasıl değiştirebilirim

Satır boyutu çok büyük (> 8126). Bazı sütunları TEXT veya BLOB olarak değiştirmek veya kullanmak ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSEDyardımcı olabilir. Mevcut satır biçiminde, BLOB768 baytlık önek satır içi olarak saklanır.

Tablo:

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
top_a   varchar(255)    No       
top_b   varchar(255)    No       
top_c   varchar(255)    No       
top_d   varchar(255)    No       
top_e   varchar(255)    No       
top_f   varchar(255)    No       
top_g   varchar(255)    No       
top_h   varchar(255)    No       
top_i   varchar(255)    No       
top_j   varchar(255)    No       
top_title_a varchar(255)    No       
top_title_b varchar(255)    No       
top_title_c varchar(255)    No       
top_title_d varchar(255)    No       
top_title_e varchar(255)    No       
top_title_f varchar(255)    No       
top_title_g varchar(255)    No       
top_title_h varchar(255)    No       
top_title_i varchar(255)    No       
top_title_j varchar(255)    No       
top_desc_a  text    No       
top_desc_b  text    No       
top_desc_c  text    No       
top_desc_d  text    No       
top_desc_e  text    No       
top_desc_f  text    No       
top_desc_g  text    No       
top_desc_h  text    No       
top_desc_i  text    No       
top_desc_j  text    No       
status  int(11) No       
admin_id    int(11) No 

1
Ne olduğunu Novarlık görüntülenen?
hjpotter92

"Satır boyutu çok büyük (> 8126) hatası güncellenemiyor. Bazı sütunların TEXT veya BLOB olarak değiştirilmesi veya ROW_FORMAT = DYNAMIC veya ROW_FORMAT = COMPRESSED kullanılması işe yarayabilir. Mevcut satır biçiminde, 768 baytlık BLOB öneki satır içi olarak saklanır."
Lasha Kurt

Gönderinize en azından yorum olarak başka ayrıntılar ekleyebilir misiniz?
Eineki

1
bu veriler başka bir tablodaysa, bunun yerine yabancı anahtar kullanmayı düşünün, bu, satır boyutunuzu önemli ölçüde azaltır ve veritabanı şemanızı normalleştirir.
2013

1
@AL: Oops, haklısın - diğerine yakın oylama
pathikrit

Yanıtlar:


122

Soru serverfault'da da soruldu .

MySQL satır boyutları hakkında çok şey açıklayan bu makaleye bir göz atmak isteyebilirsiniz . METİN veya BLOB alanlarını kullansanız bile, satır boyutunuzun hala 8K'nın üzerinde olabileceğini (InnoDB için sınır), çünkü sayfadaki her alan için ilk 768 baytı depoladığını unutmamak önemlidir.

Bunu düzeltmenin en basit yolu , InnoDB ile Barracuda dosya biçimini kullanmaktır . Bu temelde, ilk 768 baytı depolamak yerine, yalnızca 20 baytlık göstericiyi metin verilerine depolayarak sorunu tamamen ortadan kaldırır.


OP için işe yarayan yöntem şöyleydi:

  1. Aşağıdakileri bölüm my.cnfaltındaki dosyaya ekleyin [mysqld].

    innodb_file_per_table=1
    innodb_file_format = Barracuda
    
  2. ALTERkullanılacak tablo ROW_FORMAT=COMPRESSED.

    ALTER TABLE nombre_tabla
        ENGINE=InnoDB
        ROW_FORMAT=COMPRESSED 
        KEY_BLOCK_SIZE=8;
    

Yukarıdakilerin hala sorunlarınızı çözmeme olasılığı vardır. Bu bir olduğunu bilinen (ve doğrulanmış) hata ile InnoDB'nin motoru ve şimdilik geçici bir düzeltme çare olmaktır MyISAM geçici depolama olarak motora. Öyleyse, my.cnfdosyanda:

internal_tmp_disk_storage_engine=MyISAM

12
+1 -> innodb_file_per_table bölümü çok önemlidir ve biçimi Barracuda olarak değiştirmekle el ele gider. Bu olmadan MySQL sessizce Antelope kullanmaya devam edecektir.
Nick

1
@Eduardo, önce verileri yedeklemenizi tavsiye ederim. Ama evet, bunu üretimde de yapabilirsiniz!
hjpotter92

3
Kullan innodb_file_per_table=1Bu seçeneği aktif hale getirmek için.
Stijn Geukens

2
Bunun sorunu çözeceği garanti edilmez. Bu ayarları ekleyen ancak yine de hatayı yeniden oluşturabilen örnek bir komut dosyası için bu gönderiye bakın .
Cerin

1
@ user1183352 Yukarıdaki cevabım güncellendi. Bu konuya daha derin dalmamı tekrar hatırlattığın için teşekkürler. :)
hjpotter92

62

Son zamanlarda bu problemle karşılaştım ve farklı bir şekilde çözdüm. MySQL 5.6.20 sürümünü çalıştırıyorsanız, sistemde bilinen bir hata vardır. MySQL belgelerine bakın

Önemli Hata # 69477 nedeniyle, büyük, harici olarak depolanan BLOB alanları için yeniden günlük yazma işlemleri en son kontrol noktasının üzerine yazabilir. Bu hatayı gidermek için, MySQL 5.6.20'de sunulan bir yama, BLOB yeniden yazma günlük dosyası boyutunun% 10'u ile yeniden yazma boyutunu sınırlar. Bu sınırın bir sonucu olarak, innodb_log_file_size, tablolarınızın satırlarında bulunan en büyük BLOB veri boyutunun yanı sıra diğer değişken uzunluklu alanların (VARCHAR, VARBINARY ve TEXT türü alanlar) uzunluğunun 10 katından daha büyük bir değere ayarlanmalıdır.

Benim durumumda rahatsız edici blob tablosu 16MB civarındaydı. Bu nedenle, sorunu çözme şeklim my.cnf'ye bir satır ekleyerek bu miktarın en az 10 katına sahip olmamı sağladı ve sonra biraz:

innodb_log_file_size = 256M


Nokta üzerinde. Parametreyi longblobarttırdığım anda bir alandaki "Satır Boyutu çok büyük" hatam ortadan kalktı innodb_log_file_size. 5.6.20 de koşuyordu.
adamup

Teşekkürler. Homebrew 5.6.21 çalıştırıyordu, parametrenin değiştirilmesi sorunu çözdü.
nanoman

Bu hatayı benim için düzeltmek için hem bu hem de @ hjpotter92'nin cevabı gerekiyordu.
Cerin

Teşekkürler. 5.6.21 çalıştırıyordu ve bu çözüm yardımcı oldu.
petiar

Bu da sorunumu çözmedi. Benzer başlıklarda gördüğüm gibi, VARCHAR alanlarımın çoğunu METİN'lerle değiştirmeyi düşünüyorum.
PDoria

29

My.cnf dosyanızda aşağıdakileri ayarlayın ve mysql sunucunuzu yeniden başlatın.

innodb_strict_mode=0

2
innodb_strict_mode=0-> boşluk yok. Aksi takdirde, mariaDB 10.2'nin yeniden başlatılması şu hatayla sonuçlanır :-P
Pathros

Mariadb ile denemedim, MySQL için boşlukları kaldırmaya gerek yok.
Karl

1
Belgelere göre, katı modu devre dışı bırakmak yalnızca hataların ve uyarıların görünmesini engeller, bu nedenle sorunu çözmüyor gibi görünüyor! download.nust.na/pub6/mysql/doc/innodb-plugin/1.1/en/…
João Teixeira

2
Bu işe yarıyor gibi görünüyor ve tabloları sorunsuz bir şekilde oluşturmama ve verileri depolamama izin veriyor
Chris Muench

@ João, daha fazlasını yapar .. dev.mysql.com/doc/refman/8.0/en/…
Karl

23

ENGINE'i değiştirebilir ve InnoDB yerine MyISAM'ı kullanırsanız, bu yardımcı olacaktır:

ENGINE=MyISAM

MyISAM ile ilgili iki uyarı vardır (muhtemelen daha fazlası):

  1. İşlemleri kullanamazsınız.
  2. Yabancı anahtar kısıtlamalarını kullanamazsınız.

6
İşlemler ve yabancı anahtar kısıtlamaları olmadan gitmenin sakıncası yoksa iyi. Ancak MyISAM'a geçerken bunları kaybettiğinizi unutmayın.
wobbily_col

1
Bu tavsiye çılgınca - en azından ifade, uyarıları tamamlayacak! İşlemler ve foregith anahtar kısıtlamaları, bu formatla ilgili en küçük problemlerdir!
Hassan Syed

Üzgünüm, bu yanıta oy vermedim. Lütfen ilgili tüm uyarıları belirtmek için güncelleyin. Bu tavsiyeye uyan biri, hiçbir üretim sisteminde asla kullanmayacağım bir biçime geçer.
Remco Wendt

2
Ve MyISAM ortadan kalkıyor.
Rick James

2
benim için çalıştı. Benim durumumda her biri yaklaşık 10 uzunluğunda 300'den fazla alan vardı. Bu tabloda herhangi bir ilişkim yok, bu yüzden MyISAM'a geçmek düzeltmeydi.
Robert Saylor

13

Harika bir cevap paylaşmak istiyorum, yardımcı olabilir. Krediler Bill Karwin buraya bakın /dba/6598/innodb-create-table-error-row-size-too-large

InnoDB dosya formatına göre değişir. Şu anda Antelope ve Barracuda adında 2 format vardır.

Merkezi tablo alanı dosyası (ibdata1) her zaman Antelope formatındadır. Tablo başına dosya kullanırsanız, my.cnf dosyasında innodb_file_format = Barracuda ayarlayarak tek tek dosyaların Barracuda biçimini kullanmasını sağlayabilirsiniz.

Temel noktalar:

  1. InnoDB verilerinin bir 16 KB sayfası en az iki satır veri içermelidir. Ayrıca, her sayfanın bir üst bilgisi ve sayfa sağlama toplamlarını ve günlük sıra numarasını içeren bir altbilgisi vardır. Bu, satır başına 8 KB'tan biraz daha az olan sınırınızı aldığınız yerdir.

  2. INTEGER, DATE, FLOAT, CHAR gibi sabit boyutlu veri türleri bu birincil veri sayfasında depolanır ve satır boyutu sınırına dahil edilir.

  3. VARCHAR, TEXT, BLOB gibi değişken boyutlu veri türleri taşma sayfalarında saklanır, bu nedenle satır boyutu sınırına tam olarak dahil edilmezler. Antelope'da bu tür sütunlardan 768 bayta kadar, taşma sayfasında depolanmanın yanı sıra birincil veri sayfasında depolanır. Barracuda dinamik satır biçimini destekler, bu nedenle birincil veri sayfasında yalnızca 20 baytlık bir işaretçi saklayabilir.

  4. Uzunluğu kodlamak için değişken boyutlu veri türleri de 1 veya daha fazla bayt ile başlar. Ve InnoDB satır formatının bir dizi alan ofseti de vardır. Yani wiki'lerinde aşağı yukarı belgelenen bir iç yapı var.

Barracuda ayrıca taşma verileri için daha fazla depolama verimliliği elde etmek için ROW_FORMAT = SIKIŞTIRILMIŞTIR'ı destekler.

Ayrıca, iyi tasarlanmış bir tablonun satır boyutu sınırını aştığını hiç görmediğimi de yorumlamalıyım. Birinci Normal Biçimin yinelenen gruplar koşulunu ihlal etmeniz güçlü bir "kod kokusu".


8

Aynı sorunu yaşadım, bu benim için çözdü:

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;

MYSQL Belgelerinden :

DYNAMIC satır formatı, uyuyorsa (COMPACT ve REDUNDANT formatlarında olduğu gibi) tüm satırı indeks düğümünde saklama verimliliğini korur, ancak bu yeni format B-ağaç düğümlerini çok sayıda veri baytıyla doldurma sorununu ortadan kaldırır. uzun sütunlar. DİNAMİK formatı, uzun bir veri değerinin bir kısmının sayfa dışında saklanması durumunda, genellikle tüm değeri sayfa dışı saklamanın en verimli olduğu fikrine dayanır. DİNAMİK formatında, daha kısa sütunların B-ağaç düğümünde kalması muhtemeldir ve herhangi bir satır için gereken taşma sayfalarının sayısını en aza indirir.


... ama farklı bir dosya formatına ihtiyacınız var, yani zaten Barracuda'da mısınız? Çünkü bu komutu denerken bir hata alıyorumWarnings from last query: InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope
Ted

HeidiSQL'in yerleşik GUI aracılığıyla aynı komutu çalıştırmasına izin verdiğimde, bir şekilde başarılı oldu, ancak hiç yardımcı olmadı, aynı hatayı alıyorumRow size too large (>8126)
Ted

My.ini içinde innodb_file_format = Barracuda ayarlamayı deneyin ve ALTER TABLE my_tableROW_FORMAT = DYNAMIC; tekrar
multimediaxp

Evet, sonunda yaptığım şeyin bu olduğunu düşünüyorum ve sanırım bu sorunu çözdü. Ama aynı zamanda çaresizlik içinde birçok sütunu TEXT olarak değiştirdim =) Thx, aslında öyle olduğunu düşünüyorum.
Ted

Güzel!, Bunun iyi bir cevap olduğunu düşünüyorsanız, bir oy verin ve geçerli yanıt olarak kabul edin, teşekkürler!
multimediaxp

5

Saatler geçirdikten sonra çözümü buldum: Tabloyu MyISAM'a dönüştürmek için MySQL yöneticinizde aşağıdaki SQL'i çalıştırın:

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;

Sorun bir tablo oluşturma deyiminde oluyorsa çok yardımcı olmaz.
Mark Fraser

create tableaynı seçeneğe sahiptir:CREATE TABLE ... ENGINE=MyISAM ...
xebeche

3

Yedeklenmiş bir mysql veritabanını farklı bir sunucudan geri yüklemeye çalışırken bu sorunla karşılaştım. Bu sorunu benim için çözen şey, my.conf'a belirli ayarlar eklemek (yukarıdaki sorularda olduğu gibi) ve ayrıca sql yedekleme dosyasını değiştirmekti:

Adım 1: my.conf dosyasında aşağıdaki satırları ekleyin veya düzenleyin:

innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1

Adım 2 Bu hataya neden olan tablonun sql yedek dosyasında tablo oluşturma ifadesine ROW_FORMAT = DYNAMIC ekleyin:

DROP TABLE IF EXISTS `problematic_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `problematic_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
  ...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 ROW_FORMAT=DYNAMIC;

yukarıdaki önemli değişiklik ROW_FORMAT = DYNAMIC; (orignal sql yedekleme dosyasına dahil edilmedi)

Bu sorunu çözmeme yardımcı olan kaynak: MariaDB ve InnoDB MySQL Satır boyutu çok büyük


2
1. adımda açıklanan satırlarda boşluk olmamalıdır. innodb_page_size=32KBenim durumumda MariaDB 10.2'nin yeniden başlatılmasında hataya neden olduğu için hat çalışmadı. Bunun yerine, buradainnodb_strict_mode=0 açıklandığı gibi bir satır ekledim
Pathros

1
Geri bildiriminiz için teşekkürler Pathros, cevabımı güncelledim ve 1. adımdaki boşlukları kaldırdım.
matyas

MySQL <= 5.7.5: 32K için not innodb_page_size için geçerli bir seçenek değildir. Bakınız: dev.mysql.com/doc/refman/5.6/en/…
Dub Nazar

Ayrıca, değişiklik yeniden oluşturma innodb_page_sizegerektirdiğinden ibdata*, yıkıcı bir işlem olan tüm mysql sunucunuzu yeniden oluşturmak için yeniden oluşturmanız gerekir . Daha fazla bilgi için sistem
günlüğünüzü

bir kopya gibi görünüyor veya en azından en yüksek puan alan
cevaba

2

Diğer cevaplar sorulan soruya yöneliktir. Altta yatan nedeni ele alacağım: zayıf şema tasarımı.

Bir diziyi sütunlara yaymayın. Burada, yeni bir tabloda (artı id, vb.) 3 sütunluk 10 satıra dönüştürülmesi gereken 3 * 10 sütununuz var.

Masanız Mainsadece

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
status  int(11) No       
admin_id    int(11) No 

Ekstra tablonuzda ( Top)

id  int(11) No          -- for joining to Main
seq TINYINT UNSIGNED    -- containing 1..10
img   varchar(255)    No       
title varchar(255)    No       
desc  text    No    
PRIMARY KEY(id, seq)    -- so you can easily find the 10 top_titles

Her biri için 10 (veya daha az? Veya daha fazla?) Satır Topolacaktır id.

Bu, orijinal probleminizi ortadan kaldırır ve şemayı temizler. (Bu, bazı Yorumlarda tartışıldığı gibi "normalleştirme" değildir.)

Do not MyISAM geçmek; uzaklaşıyor.
Endişelenme ROW_FORMAT.

JOINBirden çok sütun yerine birden çok satırı yapmak ve işlemek için kodunuzu değiştirmeniz gerekecektir .


1

AWS RDS'de MySQL 5.6 kullanıyorum. Aşağıdakileri parametre grubunda güncelledim.

innodb_file_per_table=1
innodb_file_format = Barracuda

Parametre grubu değişikliklerinin geçerli olması için DB örneğini yeniden başlatmak zorunda kaldım.

Ayrıca, ROW_FORMAT = COMPRESSED desteklenmedi. DİNAMİK'i aşağıdaki gibi kullandım ve iyi çalıştı.

ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8

1

Bir veritabanı sayfasında yerel olarak depolanan veriler için geçerli olan bir InnoDB tablosu için maksimum satır boyutu 4KB, 8KB, 16KB ve 32KB için yarım sayfanın biraz altındadır.

16 kb sayfalar (varsayılan) için şunları hesaplayabiliriz:

Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum

Temel olarak, bir satırı şununla maksimize edebilirsiniz:

  • 11 varchar alanı> 767 karakter (karakter başına latin1 = 1 bayt) veya
  • 11 varchar alanı> 255 karakter (mysql'de utf-8 = karakter başına 3 bayt).

Unutmayın, alan> 767 bayt ise bir taşma sayfasına taşar. 767 baytlık çok fazla alan varsa, bu patlayacaktır (maksimum satır boyutunun ötesine geçerek). Latin1 ile normal değil, ancak geliştiriciler dikkatli olmazsa utf-8 ile çok mümkün.

Bu durumda, innodb_page_size değerini 32kb'ye yükseltebileceğinizi düşünüyorum.

my.cnf dosyasında:

innodb_page_size=32K

Referanslar:


0

Ben de aynı problemle karşılaştım. Aşağıdaki sql'yi çalıştırarak sorunu çözüyorum:

ALTER ${table} ROW_FORMAT=COMPRESSED;

Ama bence Satır Depolama hakkında bilgi sahibi olmalısın .
İki tür sütun vardır: değişken uzunluklu sütun (VARCHAR, VARBINARY ve BLOB ve TEXT türleri gibi) ve sabit uzunluklu sütun . Farklı türde sayfalarda saklanırlar.

Değişken uzunluklu sütunlar bu kuralın bir istisnasıdır. B-ağaç sayfasına sığamayacak kadar uzun olan BLOB ve VARCHAR gibi sütunlar, taşma sayfaları adı verilen ayrı ayrı ayrılmış disk sayfalarında saklanır. Bu tür sütunlara sayfa dışı sütunlar diyoruz. Bu sütunların değerleri, tek tek bağlantılı taşma sayfalarının listelerinde saklanır ve bu tür her sütunun, bir veya daha fazla taşma sayfasından oluşan kendi listesi vardır. Bazı durumlarda, depolama israfını önlemek ve ayrı bir sayfa okuma ihtiyacını ortadan kaldırmak için uzun sütun değerinin tamamı veya bir öneki B ağacında saklanır.

ve ROW_FORMAT ayarının amacı

ROW_FORMAT = DYNAMIC veya ROW_FORMAT = COMPRESSED ile bir tablo oluşturulduğunda InnoDB, uzun değişken uzunluklu sütun değerlerini (VARCHAR, VARBINARY ve BLOB ve TEXT türleri için) tamamen sayfa dışı olarak depolayabilir ve kümelenmiş dizin kaydı yalnızca 20- taşma sayfasına giden bayt işaretçisi.

DİNAMİK ve SIKIŞTIRILMIŞ Satır Biçimleri hakkında daha fazla bilgi edinmek istiyorum


0

Bu, çok sayıda sütun içeren bir SELECT'te meydana gelirse, nedeni mysql'nin geçici bir tablo oluşturması olabilir. Bu tablo belleğe sığmayacak kadar büyükse, onu Diskte depolamak için InnoDB olan varsayılan geçici tablo biçimini kullanır. Bu durumda InnoDB boyut sınırları geçerlidir.

O zaman 4 seçeneğiniz var:

  1. sunucunun yeniden başlatılmasını gerektiren başka bir gönderide belirtildiği gibi innodb satır boyutu sınırını değiştirin.
  2. Sorgunuzu daha az sütun içerecek şekilde değiştirin veya geçici bir tablo oluşturmasına neden olmaktan kaçının (yani sıralama ve sınır cümlelerini kaldırarak).
  3. max_heap_table_size büyük olacak şekilde değiştirilir, böylece sonuç belleğe sığar ve diske yazılmasına gerek kalmaz.
  4. varsayılan geçici tablo formatını MYISAM olarak değiştirin, yaptığım buydu. My.cnf dosyasındaki değişiklik:

    internal_tmp_disk_storage_engine=MYISAM

Mysql'i yeniden başlatın, sorgu çalışır.


0

İşte ilgilenen herkes için basit bir ipucu:

Debian 9'dan Debian 10'a 10.3.17-MariaDB ile yükselttikten sonra, Joomla veritabanlarında bazı hatalar alıyorum:

InnoDB [Uyarı]: alanına eklenemez fieldtabloda database. tableçünkü ekledikten sonra, satır boyutu 8742'dir ve bu, dizin sayfası sayfasındaki bir kayıt için izin verilen maksimum boyuttan (8126) daha büyüktür.

Her ihtimale karşı, /etc/mysql/mariadb.conf.d/50-server.cnf içinde innodb_default_row_format = DYNAMIC ayarladım (yine de varsayılan idi)

Daha sonra, Joomla veritabanındaki tüm tablolar için "Optimize tablosu" nu çalıştırmak için phpmyadmin'i kullandım. Süreç içinde phpmyadmin tarafından yapılan masa rekreasyonunun yardımcı olduğunu düşünüyorum. Eğer phpmyadmin'i kurduysanız, sadece birkaç tıklama yeterlidir.


Joomla kullanıcısıysanız, gelin Joomla Stack Exchange'de bize katılın - her zaman yeni katılımcılar kullanabiliriz.
mickmackusa
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.