เปลี่ยนขีด จำกัด สำหรับ“ ขนาดแถว Mysql ใหญ่เกินไป”


104

ฉันจะเปลี่ยนขีด จำกัด ได้อย่างไร

ขนาดแถวใหญ่เกินไป (> 8126) การเปลี่ยนบางคอลัมน์เป็น TEXT หรือ BLOB หรือใช้ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSEDอาจช่วยได้ ในรูปแบบแถวปัจจุบันBLOBคำนำหน้าขนาด 768 ไบต์จะถูกเก็บไว้ในบรรทัด

ตาราง:

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
สิ่งที่Noกำลังแสดงอยู่?
hjpotter92

ไม่สามารถอัปเดตข้อผิดพลาด "ขนาดแถวใหญ่เกินไป (> 8126) การเปลี่ยนบางคอลัมน์เป็น TEXT หรือ BLOB หรือใช้ ROW_FORMAT = DYNAMIC หรือ ROW_FORMAT = COMPRESSED อาจช่วยได้ในรูปแบบแถวปัจจุบันคำนำหน้า BLOB ที่ 768 ไบต์จะถูกเก็บไว้ในบรรทัด"
Lasha Kurt

คุณสามารถเพิ่มรายละเอียดอื่น ๆ ในโพสต์ของคุณอย่างน้อยก็เป็นความคิดเห็นได้หรือไม่?
Eineki

1
หากข้อมูลนี้อยู่ในตารางอื่นให้พิจารณาใช้คีย์นอกแทนซึ่งจะลดขนาดแถวของคุณลงอย่างมากและทำให้สคีมาฐานข้อมูลของคุณเป็นปกติ
didierc

1
@AL: อ๊ะคุณพูดถูก - ปิดโหวตคนอื่น
pathikrit

คำตอบ:


121

มีการถามคำถามในserverfaultด้วย

คุณอาจต้องการดูบทความนี้ซึ่งอธิบายมากมายเกี่ยวกับขนาดแถว MySQL โปรดทราบว่าแม้ว่าคุณจะใช้ฟิลด์ TEXT หรือ BLOB ขนาดแถวของคุณอาจเกิน 8K (ขีด จำกัด สำหรับ InnoDB) เนื่องจากเก็บข้อมูล 768 ไบต์แรกสำหรับแต่ละฟิลด์แบบอินไลน์ในเพจ

วิธีที่ง่ายที่สุดในการแก้ไขปัญหานี้คือการใช้รูปแบบไฟล์ Barracuda กับ InnoDB โดยพื้นฐานแล้วสิ่งนี้จะกำจัดปัญหาโดยสิ้นเชิงโดยการจัดเก็บเฉพาะตัวชี้ 20 ไบต์ไปยังข้อมูลข้อความแทนที่จะเก็บ 768 ไบต์แรก


วิธีการที่ใช้ได้กับ OP มีดังนี้:

  1. เพิ่มสิ่งต่อไปนี้ลงในmy.cnfไฟล์ภายใต้[mysqld]ส่วน

    innodb_file_per_table=1
    innodb_file_format = Barracuda
  2. ALTERROW_FORMAT=COMPRESSEDตารางเพื่อการใช้งาน

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

มีความเป็นไปได้ที่ข้างต้นยังไม่สามารถแก้ไขปัญหาของคุณได้ เป็นข้อบกพร่องที่ทราบ (และตรวจสอบแล้ว)กับเครื่องมือInnoDBและการแก้ไขชั่วคราวในตอนนี้คือการเปลี่ยนกลับไปยังโปรแกรมMyISAMเป็นที่จัดเก็บชั่วคราว ดังนั้นในmy.cnfไฟล์ของคุณ:

internal_tmp_disk_storage_engine=MyISAM

12
+1 -> ส่วน innodb_file_per_table มีความสำคัญและควบคู่ไปกับการเปลี่ยนรูปแบบเป็น Barracuda หากไม่มี MySQL จะยังคงใช้ Antelope ต่อไป
นิค

1
@Eduardo ขอแนะนำให้สำรองข้อมูลก่อน แต่ใช่คุณสามารถทำสิ่งนี้ในการผลิตได้ด้วย!
hjpotter92

3
ใช้innodb_file_per_table=1เพื่อเปิดใช้งานตัวเลือกนี้
Stijn Geukens

2
ไม่รับประกันว่าจะแก้ไขปัญหาได้ ดูโพสต์นี้สำหรับสคริปต์ตัวอย่างที่เพิ่มการตั้งค่าเหล่านี้ แต่ยังสามารถสร้างข้อผิดพลาดซ้ำ
Cerin

1
@ user1183352 อัปเดตคำตอบของฉันด้านบน ขอขอบคุณที่เตือนฉันอีกครั้งให้เจาะลึกลงไปในเรื่องนี้ :)
hjpotter92

61

เมื่อเร็ว ๆ นี้ฉันพบปัญหานี้และแก้ไขด้วยวิธีอื่น หากคุณใช้ MySQL เวอร์ชัน 5.6.20 มีข้อผิดพลาดที่ทราบในระบบ ดูเอกสาร MySQL

สำคัญเนื่องจากข้อผิดพลาด # 69477 บันทึกการเขียนซ้ำสำหรับฟิลด์ BLOB ที่เก็บไว้ภายนอกขนาดใหญ่สามารถเขียนทับจุดตรวจสอบล่าสุดได้ เพื่อแก้ไขข้อบกพร่องนี้โปรแกรมแก้ไขที่นำมาใช้ใน MySQL 5.6.20 จะ จำกัด ขนาดของบันทึกการทำซ้ำ BLOB เขียนถึง 10% ของขนาดไฟล์บันทึกการทำซ้ำ จากผลของขีด จำกัด นี้ควรตั้งค่า innodb_log_file_size เป็นค่าที่มากกว่า 10 เท่าของขนาดข้อมูล BLOB ที่ใหญ่ที่สุดที่พบในแถวของตารางของคุณบวกกับความยาวของฟิลด์ความยาวตัวแปรอื่น ๆ (ฟิลด์ประเภท VARCHAR, VARBINARY และ TEXT)

ในสถานการณ์ของฉันตารางหยดที่กระทำผิดอยู่ที่ประมาณ 16MB ดังนั้นวิธีที่ฉันแก้ไขคือการเพิ่มบรรทัดใน my.cnf เพื่อให้แน่ใจว่าฉันมีเงินอย่างน้อย 10 เท่าจากนั้นบางส่วน:

innodb_log_file_size = 256M


จับได้เห็นชัดตรงเผง. ข้อผิดพลาด "ขนาดแถวใหญ่เกินไป" บนlongblobฟิลด์ของฉันหายไปทันทีที่ฉันเพิ่มinnodb_log_file_sizeพารามิเตอร์ ยังใช้งานได้ 5.6.20
adamup

ขอบคุณ. กำลังเรียกใช้ homebrew 5.6.21 การเปลี่ยนพารามิเตอร์ช่วยแก้ไขปัญหา
nanoman

จำเป็นต้องมีคำตอบทั้งนี้และ @ hjpotter92 เพื่อแก้ไขข้อผิดพลาดนี้ให้ฉัน
Cerin

ขอบคุณ. กำลังเรียกใช้ 5.6.21 และโซลูชันนี้ช่วยได้
petiar

สิ่งนี้ไม่สามารถแก้ปัญหาของฉันได้เช่นกัน ฉันกำลังพิจารณาเปลี่ยนฟิลด์ VARCHAR ของฉันเป็น TEXT ตามที่ฉันเห็นในเธรดที่คล้ายกัน
PDoria

28

ตั้งค่าการติดตามในไฟล์ my.cnf ของคุณและรีสตาร์ทเซิร์ฟเวอร์ mysql

innodb_strict_mode=0

2
innodb_strict_mode=0-> ไม่มีช่องว่าง มิฉะนั้นการรีสตาร์ท mariaDB 10.2 จะทำให้เกิดข้อผิดพลาด :-P
Pathros

ฉันไม่ได้ลองใช้ mariadb สำหรับ MySQL ไม่จำเป็นต้องลบช่องว่าง
Karl

1
ตามเอกสารประกอบการปิดใช้งานโหมดเข้มงวดเพียงป้องกันไม่ให้มีข้อผิดพลาดและคำเตือนปรากฏขึ้นดังนั้นดูเหมือนว่าจะแก้ปัญหาไม่ได้! download.nust.na/pub6/mysql/doc/innodb-plugin/1.1/en/…
João Teixeira

2
ดูเหมือนว่าจะได้ผลและให้ฉันสร้างตารางโดยไม่มีปัญหาและจัดเก็บข้อมูล
Chris Muench

@ Joãoมันทำได้มากกว่า .. dev.mysql.com/doc/refman/8.0/en/…
Karl

23

หากคุณสามารถเปลี่ยน ENGINE และใช้ MyISAM แทน InnoDB ได้สิ่งนี้จะช่วยได้:

ENGINE=MyISAM

MyISAM มีข้อแม้สองประการ (เนื้อหามีมากกว่านั้น):

  1. คุณไม่สามารถใช้ธุรกรรมได้
  2. คุณไม่สามารถใช้ข้อ จำกัด ของคีย์ต่างประเทศ

6
ดีถ้าคุณไม่คิดที่จะดำเนินการโดยไม่มีธุรกรรมและข้อ จำกัด ของคีย์ต่างประเทศ แต่โปรดทราบว่าคุณสูญเสียสิ่งเหล่านี้เมื่อเปลี่ยนเป็น MyISAM
wobbily_col

1
คำแนะนำนี้เป็นเรื่องบ้า - อย่างน้อยวลีก็จะเป็นคำเตือน! การทำธุรกรรมและข้อ จำกัด ที่สำคัญของ foregith เป็นปัญหาน้อยที่สุดในรูปแบบนี้!
Hassan Syed

ขออภัยที่ลงคะแนนคำตอบนี้ โปรดอัปเดตเพื่อระบุคำเตือนทั้งหมดที่เกี่ยวข้อง ใครก็ตามที่ทำตามคำแนะนำนี้จะเปลี่ยนไปใช้รูปแบบที่ฉันไม่เคยใช้กับระบบการผลิตใด ๆ
Remco Wendt

2
และ MyISAM กำลังจะหายไป
Rick James

2
ทำงานให้ฉัน กรณีของฉันฉันมีฟิลด์มากกว่า 300 ฟิลด์โดยมีความยาวประมาณ 10 ฟิลด์ ฉันไม่มีความสัมพันธ์ใด ๆ ในตารางนี้ดังนั้นการเปลี่ยนไปใช้ MyISAM จึงเป็นการแก้ไข
Robert Saylor

12

ฉันต้องการแบ่งปันคำตอบที่ยอดเยี่ยมซึ่งอาจเป็นประโยชน์ เครดิต Bill Karwin ดูที่นี่/dba/6598/innodb-create-table-error-row-size-too-large

แตกต่างกันไปตามรูปแบบไฟล์ InnoDB ปัจจุบันมี 2 รูปแบบที่เรียกว่า Antelope และ Barracuda

ไฟล์พื้นที่ตารางกลาง (ibdata1) จะอยู่ในรูปแบบ Antelope เสมอ หากคุณใช้ไฟล์ต่อตารางคุณสามารถทำให้แต่ละไฟล์ใช้รูปแบบ Barracuda ได้โดยตั้งค่า innodb_file_format = Barracuda ใน my.cnf

คะแนนพื้นฐาน:

  1. ข้อมูล InnoDB ขนาด 16KB หนึ่งหน้าต้องมีข้อมูลอย่างน้อยสองแถว นอกจากนี้แต่ละหน้ายังมีส่วนหัวและส่วนท้ายที่มีการตรวจสอบหน้าและหมายเลขลำดับการบันทึกเป็นต้น นั่นคือที่ที่คุณจะได้รับขีด จำกัด น้อยกว่า 8KB ต่อแถว

  2. ประเภทข้อมูลขนาดคงที่เช่น INTEGER, DATE, FLOAT, CHAR จะถูกเก็บไว้ในหน้าข้อมูลหลักนี้และนับรวมในขีด จำกัด ขนาดแถว

  3. ชนิดข้อมูลที่ปรับขนาดได้เช่น VARCHAR, TEXT, BLOB จะถูกจัดเก็บในเพจล้นดังนั้นจึงไม่นับรวมในขีด จำกัด ขนาดแถว ใน Antelope คอลัมน์ดังกล่าวมากถึง 768 ไบต์จะถูกจัดเก็บไว้ในหน้าข้อมูลหลักนอกเหนือจากการจัดเก็บในเพจโอเวอร์โฟลว์ Barracuda รองรับรูปแบบแถวแบบไดนามิกดังนั้นจึงอาจจัดเก็บเพียงตัวชี้ 20 ไบต์ในหน้าข้อมูลหลัก

  4. ชนิดข้อมูลขนาดตัวแปรจะมีคำนำหน้า 1 ไบต์หรือมากกว่าเพื่อเข้ารหัสความยาว และรูปแบบแถว InnoDB ยังมีอาร์เรย์ของการชดเชยฟิลด์ ดังนั้นจึงมีโครงสร้างภายในที่บันทึกไว้ในวิกิของพวกเขาไม่มากก็น้อย

Barracuda ยังสนับสนุน ROW_FORMAT = COMPRESSED เพื่อเพิ่มประสิทธิภาพในการจัดเก็บข้อมูลเพิ่มเติมสำหรับข้อมูลล้น

ฉันต้องแสดงความคิดเห็นด้วยว่าฉันไม่เคยเห็นตารางที่ออกแบบมาอย่างดีเกินขีด จำกัด ขนาดแถว เป็น "กลิ่นรหัส" ที่รุนแรงซึ่งคุณกำลังละเมิดเงื่อนไขการทำซ้ำกลุ่มของ First Normal Form


7

ฉันมีปัญหาเดียวกันสิ่งนี้แก้ไขได้สำหรับฉัน:

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;

จากเอกสาร MYSQL :

รูปแบบแถว DYNAMIC จะรักษาประสิทธิภาพในการจัดเก็บทั้งแถวในโหนดดัชนีหากเหมาะสม (เช่นเดียวกับรูปแบบ COMPACT และ REDUNDANT) แต่รูปแบบใหม่นี้จะหลีกเลี่ยงปัญหาในการเติมโหนด B-tree ด้วยจำนวนไบต์ข้อมูลจำนวนมาก คอลัมน์ยาว รูปแบบ DYNAMIC มีพื้นฐานมาจากแนวคิดที่ว่าหากส่วนหนึ่งของค่าข้อมูลที่ยาวถูกจัดเก็บไว้นอกหน้ามักจะมีประสิทธิภาพสูงสุดในการจัดเก็บค่าทั้งหมดไว้นอกหน้า ด้วยรูปแบบ DYNAMIC คอลัมน์ที่สั้นกว่ามีแนวโน้มที่จะยังคงอยู่ในโหนด B-tree ลดจำนวนเพจล้นที่จำเป็นสำหรับแถวที่ระบุ


... แต่คุณต้องมีรูปแบบไฟล์อื่นดังนั้นคุณอยู่ที่ Barracuda แล้วหรือยัง? สาเหตุที่ฉันได้รับข้อผิดพลาดในการลองใช้คำสั่งนั้นWarnings from last query: InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope
Ted

เมื่อฉันปล่อยให้ HeidiSQL รันคำสั่งเดียวกันผ่าน GUI ในตัวมันก็ประสบความสำเร็จ แต่ก็ไม่ได้ช่วยอะไรเลยฉันได้รับข้อผิดพลาดเดียวกันRow size too large (>8126)
Ted

ลองตั้งค่า innodb_file_format = Barracuda ใน my.ini แล้วลอง ALTER TABLE my_tableROW_FORMAT = DYNAMIC; อีกครั้ง
multimediaxp

ใช่ฉันคิดว่านั่นคือสิ่งที่ฉันทำในตอนท้ายจริงๆและฉันคิดว่ามันสามารถแก้ไขได้ แต่ฉันยังเปลี่ยนคอลัมน์จำนวนมากเป็น TEXT ในเวลาเดียวกันด้วยความสิ้นหวัง =) ขอบคุณจริงๆฉันคิดว่ามันเป็นอย่างนั้น
เทด

ดี! ถ้าคุณคิดว่านี่เป็นคำตอบที่ดีให้โหวตและยอมรับว่าเป็นคำตอบที่ถูกต้องขอบคุณ!
Multimediaxp

5

หลังจากใช้เวลาหลายชั่วโมงฉันพบวิธีแก้ปัญหา: เพียงเรียกใช้ SQL ต่อไปนี้ในผู้ดูแลระบบ MySQL ของคุณเพื่อแปลงตารางเป็น MyISAM:

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;

ไม่ได้ช่วยอะไรมากหากปัญหาเกิดขึ้นในคำสั่งสร้างตาราง
Mark Fraser

create tableมีตัวเลือกเดียวกัน:CREATE TABLE ... ENGINE=MyISAM ...
xebeche

3

ฉันพบปัญหานี้เมื่อฉันพยายามกู้คืนฐานข้อมูล mysql ที่สำรองไว้จากเซิร์ฟเวอร์อื่น สิ่งที่แก้ไขปัญหานี้สำหรับฉันคือการเพิ่มการตั้งค่าบางอย่างใน my.conf (เช่นในคำถามด้านบน) และการเปลี่ยนไฟล์สำรอง sql เพิ่มเติม:

ขั้นตอนที่ 1: เพิ่มหรือแก้ไขบรรทัดต่อไปนี้ใน my.conf:

innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1

ขั้นตอนที่ 2เพิ่ม ROW_FORMAT = DYNAMIC ลงในตารางสร้างคำสั่งในไฟล์สำรอง sql สำหรับตารางที่ทำให้เกิดข้อผิดพลาดนี้:

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;

การเปลี่ยนแปลงที่สำคัญข้างต้นคือROW_FORMAT = DYNAMIC; (ที่ไม่รวมอยู่ในไฟล์สำรองของ orignal sql)

แหล่งที่มาที่ช่วยฉันแก้ไขปัญหานี้: MariaDB และ InnoDB MySQL Row มีขนาดใหญ่เกินไป


1
เส้นที่อธิบายในขั้นตอนที่ 1 ไม่ควรมีช่องว่าง Line innodb_page_size=32Kไม่ทำงานเนื่องจากทำให้เกิดข้อผิดพลาดในการรีสตาร์ท MariaDB 10.2 ในกรณีของฉัน แต่ฉันเพิ่มinnodb_strict_mode=0บรรทัดตามที่อธิบายไว้ที่นี่
Pathros

1
ขอบคุณสำหรับคำติชม Pathros ฉันอัปเดตคำตอบและลบช่องว่างจากขั้นตอนที่ 1
matyas

หมายเหตุสำหรับ MySQL <= 5.7.5: 32K ไม่ใช่ตัวเลือกที่ถูกต้องสำหรับ innodb_page_size ดู: dev.mysql.com/doc/refman/5.6/en/…
พากย์ Nazar

นอกจากนี้คุณต้องสร้างเซิร์ฟเวอร์ mysql ใหม่ทั้งหมดสำหรับ scracth เนื่องจากการเปลี่ยนแปลงinnodb_page_sizeต้องใช้การibdata*พักผ่อนหย่อนใจซึ่งเป็นการดำเนินการทำลายล้าง ดู syslog ของคุณสำหรับข้อมูลเพิ่มเติม
Matija Nalis

2

คำตอบอื่น ๆ ตอบคำถามที่ถาม ฉันจะพูดถึงสาเหตุพื้นฐาน: การออกแบบสคีมาที่ไม่ดี

อย่าแยกอาร์เรย์ข้ามคอลัมน์ ที่นี่คุณมี 3 * 10 คอลัมน์ที่ควรเปลี่ยนเป็น 10 แถว 3 คอลัมน์ในตารางใหม่ (บวกidฯลฯ )

Mainโต๊ะของคุณจะมีเพียง

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 

โต๊ะเสริมของคุณ ( 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

จะมี 10 (หรือน้อยกว่า? หรือมากกว่า?) แถวในแต่ละTopid

วิธีนี้ช่วยขจัดปัญหาเดิมของคุณและล้างสคีมา (นี่ไม่ใช่ "การทำให้เป็นมาตรฐาน" ตามที่ถกเถียงกันในบางความคิดเห็น)

ทำไม่ได้เปลี่ยนไป MyISAM; มันกำลังจะหายไป ไม่ต้องกังวลกับ
ROW_FORMAT

คุณจะต้องเปลี่ยนรหัสของคุณเพื่อทำJOINและจัดการหลายแถวแทนที่จะเป็นหลายคอลัมน์


1

ฉันใช้ MySQL 5.6 บน AWS RDS ฉันอัปเดตการติดตามในกลุ่มพารามิเตอร์

innodb_file_per_table=1
innodb_file_format = Barracuda

ฉันต้องรีบูตอินสแตนซ์ DB เพื่อให้การเปลี่ยนแปลงกลุ่มพารามิเตอร์มีผล

นอกจากนี้ไม่รองรับ ROW_FORMAT = COMPRESSED ฉันใช้ DYNAMIC ดังต่อไปนี้และใช้งานได้ดี

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

1

ขนาดแถวสูงสุดสำหรับตาราง InnoDB ซึ่งใช้กับข้อมูลที่จัดเก็บภายในเพจฐานข้อมูลน้อยกว่าครึ่งหน้าเล็กน้อยสำหรับ 4KB, 8KB, 16KB และ 32KB

สำหรับหน้า 16kb (ค่าเริ่มต้น) เราสามารถคำนวณ:

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

โดยทั่วไปคุณสามารถเพิ่มจำนวนแถวได้สูงสุดด้วย:

  • 11 ช่อง varchar> 767 อักขระ (latin1 = 1 ไบต์ต่ออักขระ) หรือ
  • 11 ฟิลด์ varchar> 255 อักขระ (utf-8 บน mysql = 3 ไบต์ต่อถ่าน)

โปรดจำไว้ว่ามันจะล้นไปยังเพจโอเวอร์โฟลว์ถ้าฟิลด์> 767 ไบต์ หากมีฟิลด์ 767 ไบต์มากเกินไปฟิลด์จะหยุด (ผ่านเกิน row_size สูงสุด) ไม่ปกติกับ latin1 แต่เป็นไปได้มากกับ utf-8 หากนักพัฒนาไม่ระมัดระวัง

สำหรับกรณีนี้ฉันคิดว่าคุณสามารถชน innodb_page_size เป็น 32kb ได้

ใน my.cnf:

innodb_page_size=32K

อ้างอิง:


0

ฉันยังพบปัญหาเดียวกัน ฉันแก้ปัญหาโดยเรียกใช้ sql ต่อไปนี้:

ALTER ${table} ROW_FORMAT=COMPRESSED;

แต่ผมคิดว่ายูควรรู้เกี่ยวกับการจัดเก็บแถว
คอลัมน์มีสองประเภท: คอลัมน์ที่มีความยาวผันแปรได้ (เช่น VARCHAR, VARBINARY และ BLOB และ TEXT) และความยาวคงที่คอลัมน์ ซึ่งจะถูกจัดเก็บไว้ในเพจประเภทต่างๆ

คอลัมน์ที่มีความยาวตัวแปรเป็นข้อยกเว้นของกฎนี้ คอลัมน์เช่น BLOB และ VARCHAR ที่ยาวเกินไปที่จะพอดีกับเพจ B-tree จะถูกเก็บไว้ในดิสก์เพจที่จัดสรรแยกกันเรียกว่าเพจโอเวอร์โฟลว์ เราเรียกคอลัมน์ดังกล่าวว่าคอลัมน์นอกหน้า ค่าของคอลัมน์เหล่านี้จะถูกจัดเก็บไว้ในรายการโอเวอร์โฟลว์เพจที่เชื่อมโยงแบบเอกเทศและแต่ละคอลัมน์ดังกล่าวมีรายการของเพจล้นอย่างน้อยหนึ่งเพจ ในบางกรณีคำนำหน้าค่าคอลัมน์แบบยาวทั้งหมดหรือคำนำหน้าจะถูกเก็บไว้ใน B-tree เพื่อหลีกเลี่ยงการสิ้นเปลืองพื้นที่จัดเก็บข้อมูลและไม่จำเป็นต้องอ่านแยกหน้า

และเมื่อจุดประสงค์ของการตั้งค่า ROW_FORMAT คือ

เมื่อสร้างตารางด้วย ROW_FORMAT = DYNAMIC หรือ ROW_FORMAT = COMPRESSED InnoDB สามารถจัดเก็บค่าคอลัมน์ที่มีความยาวตัวแปรแบบยาว (สำหรับประเภท VARCHAR, VARBINARY และ BLOB และ TEXT) แบบเต็มนอกหน้าโดยระเบียนดัชนีคลัสเตอร์มีเพียง 20- ตัวชี้ไบต์ไปยังหน้ารายการเพิ่มเติม

ต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับDYNAMIC และ COMPRESSED Row Formats


0

หากสิ่งนี้เกิดขึ้นใน SELECT ที่มีหลายคอลัมน์สาเหตุอาจเป็นไปได้ว่า mysql กำลังสร้างตารางชั่วคราว หากตารางนี้มีขนาดใหญ่เกินไปที่จะใส่ลงในหน่วยความจำตารางนี้จะใช้รูปแบบตารางอุณหภูมิเริ่มต้นซึ่งเป็น InnoDB เพื่อจัดเก็บไว้ในดิสก์ ในกรณีนี้จะใช้ขีด จำกัด ขนาด InnoDB

จากนั้นคุณมี 4 ตัวเลือก:

  1. เปลี่ยนขีด จำกัด ขนาดแถว innodb ตามที่ระบุไว้ในโพสต์อื่นซึ่งต้องมีการเริ่มต้นเซิร์ฟเวอร์ใหม่
  2. เปลี่ยนคำค้นหาของคุณให้มีคอลัมน์น้อยลงหรือหลีกเลี่ยงไม่ให้สร้างตารางชั่วคราว (โดยการลบลำดับโดยและ จำกัด อนุประโยค)
  3. การเปลี่ยนmax_heap_table_sizeเป็นขนาดใหญ่เพื่อให้ผลลัพธ์พอดีกับหน่วยความจำและไม่จำเป็นต้องเขียนลงดิสก์
  4. เปลี่ยนรูปแบบตารางอุณหภูมิเริ่มต้นเป็น MYISAM นี่คือสิ่งที่ฉันทำ เปลี่ยน my.cnf:

    internal_tmp_disk_storage_engine=MYISAM

รีสตาร์ท mysql แบบสอบถามใช้งานได้


0

นี่คือเคล็ดลับง่ายๆสำหรับทุกคนที่สนใจ:

หลังจากอัปเกรดจาก Debian 9 เป็น Debian 10 ด้วย 10.3.17-MariaDB ฉันมีข้อผิดพลาดบางอย่างจากฐานข้อมูล Joomla:

[คำเตือน] InnoDB: ไม่สามารถเพิ่มเขตข้อมูลในตารางfield เนื่องจากหลังจากเพิ่มแล้วขนาดของแถวคือ 8742 ซึ่งมากกว่าขนาดสูงสุดที่อนุญาต (8126) สำหรับบันทึกในหน้าแผ่นดัชนีdatabasetable

ในกรณีนี้ฉันตั้งค่า innodb_default_row_format = DYNAMIC ใน /etc/mysql/mariadb.conf.d/50-server.cnf (มันเป็นค่าเริ่มต้นอยู่ดี)

ฉันใช้ phpmyadmin เพื่อเรียกใช้ "Optimize table" สำหรับตารางทั้งหมดในฐานข้อมูล Joomla ฉันคิดว่าการเล่นบนโต๊ะโดย phpmyadmin ในกระบวนการนี้ช่วยได้ หากคุณบังเอิญติดตั้ง phpmyadmin ไว้เพียงไม่กี่คลิกที่จะทำ


หากคุณเป็นผู้ใช้ Joomla มาร่วมกับเราที่Joomla Stack Exchange - เราสามารถใช้ผู้ร่วมให้ข้อมูลใหม่ได้ตลอดเวลา
mickmackusa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.