MySQL InnoDB ไม่ปล่อยพื้นที่ดิสก์หลังจากลบแถวข้อมูลออกจากตาราง


140

ฉันมีตาราง MySQL หนึ่งตารางที่ใช้เอ็นจิ้นการจัดเก็บ InnoDB มันมีแถวข้อมูลประมาณ 2M เมื่อฉันลบแถวข้อมูลออกจากตารางมันจะไม่ปล่อยพื้นที่ดิสก์ที่จัดสรร ขนาดของไฟล์ ibdata1 ไม่ลดลงหลังจากรันoptimize tableคำสั่ง

มีวิธีการเรียกคืนพื้นที่ดิสก์จาก MySQL หรือไม่

ฉันอยู่ในสถานการณ์ที่ไม่ดี แอปพลิเคชั่นนี้ทำงานในสถานที่ต่างกันประมาณ 50 แห่งและขณะนี้ปัญหาเรื่องพื้นที่ดิสก์เหลือน้อยปรากฏขึ้นเกือบทั้งหมด


หลังจากรันคำสั่ง optimization แล้วขนาดของไฟล์ ibdata1 ก็ไม่ได้ลดลง
Sumit Deo

4
ผมคิดว่าที่ความคิดเห็นจะได้รับการแก้ไขที่ดีขึ้นในคำตอบของคุณแล้วลบ
เบน Millwood

ซ้ำได้ของstackoverflow.com/q/11751792/82114 (แต่อันนี้อยู่ที่นี่ก่อน)
FlipMcF

1
"ขนาดของไฟล์ ibdata1 ไม่ลดลงหลังจากเรียกใช้คำสั่งเพิ่มประสิทธิภาพตาราง"นั่นเป็นเพราะคุณinnodb_file_per_tableถูกปิด ข่าวดีก็คือว่าตัวเลือกนี้เป็นonค่าเริ่มต้นใน MySQL รุ่นล่าสุด
นักบัญชีم

ฉันเรียกใช้ "optimization table xxxx" และได้รับข้อความ "Table ไม่สนับสนุนการปรับให้เหมาะสมทำการสร้าง + วิเคราะห์แทน" หลังจากรัน "du -h / var / lib / mysql" บนเชลล์ฉันสามารถดูฐานข้อมูลหดได้
user1097111

คำตอบ:


137

MySQL ไม่ลดขนาดของ ibdata1 เคย. แม้ว่าคุณoptimize tableจะใช้เพื่อเพิ่มพื้นที่ว่างที่ใช้จากระเบียนที่ถูกลบมันจะนำมาใช้ใหม่ในภายหลัง

อีกทางเลือกหนึ่งคือการกำหนดค่าเซิร์ฟเวอร์ที่จะใช้innodb_file_per_tableแต่จะต้องมีการสำรองข้อมูลวางฐานข้อมูลและเรียกคืน ด้านบวกคือว่าแฟ้ม .ibd optimize tableสำหรับตารางจะลดลงหลังจาก


4
MySQL 5.5 เอกสารเกี่ยวกับสถานะโหมดไฟล์ต่อตาราง InnoDB "เพื่อใช้ประโยชน์จากคุณสมบัติ [InnoDB ไฟล์ต่อตาราง] สำหรับตารางที่มีอยู่คุณสามารถเปิดการตั้งค่าไฟล์ต่อตารางและเรียกใช้ALTER TABLE t ENGINE=INNODBบนตารางที่มีอยู่ " หมายความว่าคุณสามารถเปิดใช้คุณสมบัตินี้ "แปลง" ตารางที่มีอยู่เพื่อใช้ไฟล์ InnoDB แยกต่างหากด้วยคำสั่ง ALTER TABLE จากนั้นปรับตารางเพื่อย่อขนาดของมัน แต่เมื่อคุณทำเสร็จแล้วคุณจะต้องคิดออกว่าจะลบ (ขนาดใหญ่) แฟ้มแหล่งที่มา InnoDB ...
จอช

9
ฉันเดาว่านี่เป็นคำตอบทางเทคนิค แต่ฉันคาดหวังว่าคนส่วนใหญ่ที่ค้นหาหัวข้อนี้กำลังมองหากระบวนการที่แท้จริงเพื่อลดขนาด / เรียกคืนพื้นที่ซึ่งคำตอบนี้ไม่ได้ให้ไว้
Manachi

@Manachi กระบวนการนี้คือ "กำหนดค่าเซิร์ฟเวอร์ให้ใช้ innodb_file_per_table", "สำรองข้อมูล" เซิร์ฟเวอร์, "ปล่อยฐานข้อมูล", หยุด mysql, ลบ. ibd, เริ่มต้นเซิร์ฟเวอร์และกู้คืนฐานข้อมูล ด้วย MySQL 5.5+ คุณสามารถใช้สิ่งที่ Josh พูดและหลังจากเปลี่ยนตารางทั้งหมดหยุดเซิร์ฟเวอร์ลบ. ibd ขนาดใหญ่และเริ่มต้นอีกครั้ง
Leonel Martins

39

เพิ่งมีปัญหาเดียวกันกับตัวเอง

สิ่งที่เกิดขึ้นคือแม้ว่าคุณจะปล่อยฐานข้อมูล innodb จะยังไม่ปล่อยพื้นที่ว่างในดิสก์ ฉันต้องส่งออกหยุด mysql ลบไฟล์ด้วยตนเองเริ่ม mysql สร้างฐานข้อมูลและผู้ใช้แล้วนำเข้า ขอบคุณพระเจ้าที่ฉันมีจำนวนแถว 200MB เท่านั้น แต่มันมีขนาดไฟล์ 250GB ของ Innodb

การออกแบบล้มเหลว


10
ใช่นั่นเป็นความล้มเหลวอย่างแน่นอน
trusktr

1
MySql 5.5 มีปัญหาเดียวกัน: ฉันรัน "optimization table" เพื่อลดการใช้ดิสก์ของตาราง 28GB การดำเนินการอาจพยายามทำโคลนที่ได้รับการปรับปรุงให้ดีที่สุดจากต้นฉบับและใช้พื้นที่ทั้งหมดในพาร์ติชันจนหมด ตอนนี้ "ตารางการปรับให้เหมาะสม" ล้มเหลวและฉันไม่มีที่เหลือในพาร์ติชันแม้หลังจากที่ฉันทำ db ทั้งหมดหายไป ... น่าผิดหวังมาก
basilikode

1
และอีก 4 ปีต่อมาฉันพบปัญหาเดียวกันกับ MySQL MS SQL จะคล้ายกัน: dba.stackexchange.com/questions/47310/…
Csaba Toth

24

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

The How Toค่อนข้างลึกซึ้ง - แต่ฉันวางส่วนที่เกี่ยวข้องไว้ด้านล่าง

อย่าลืมเก็บสำเนาของสคีมาของคุณไว้ในดัมพ์ของคุณด้วย

ปัจจุบันคุณไม่สามารถลบไฟล์ข้อมูลออกจาก tablespace ของระบบ หากต้องการลดขนาดพื้นที่ตารางระบบให้ใช้ขั้นตอนนี้:

ใช้ mysqldump เพื่อถ่ายโอนข้อมูลตาราง InnoDB ทั้งหมดของคุณ

หยุดเซิร์ฟเวอร์

ลบไฟล์ tablespace ที่มีอยู่ทั้งหมดรวมถึงไฟล์ ibdata และ ib_log หากคุณต้องการเก็บสำเนาสำรองข้อมูลไว้ให้คัดลอกไฟล์ ib * ทั้งหมดไปยังตำแหน่งอื่นก่อนที่จะลบไฟล์ในการติดตั้ง MySQL ของคุณ

ลบไฟล์. frm ใด ๆ สำหรับตาราง InnoDB

กำหนดค่าพื้นที่ตารางใหม่

รีสตาร์ทเซิร์ฟเวอร์

อิมพอร์ตไฟล์ดัมพ์


ขอขอบคุณสำหรับการรวมขั้นตอน - AFAICT ว่า 'วิธีการ' เชื่อมโยงไม่ได้มีข้อมูลนี้อีกต่อไป
Aland

3

สิบปีต่อมาและฉันมีปัญหาเดียวกัน ฉันแก้ไขมันด้วยวิธีต่อไปนี้:

  • ฉันปรับฐานข้อมูลทั้งหมดให้ดีที่สุด
  • ฉันรีสตาร์ทคอมพิวเตอร์และ MySQL บนบริการ (Windows + r -> services.msc)

นั้นคือทั้งหมด :)


1

วิธีอื่นในการแก้ปัญหาการเรียกคืนพื้นที่คือการสร้างหลายพาร์ติชันภายในตาราง - พาร์ติชันตามช่วงพาร์ติชันตามมูลค่าและเพียงแค่เลื่อน / ตัดพาร์ติชันเพื่อเรียกคืนพื้นที่ซึ่งจะปล่อยพื้นที่ที่ใช้โดยข้อมูลทั้งหมด

จะมีการเปลี่ยนแปลงบางอย่างที่จำเป็นใน schema ของตารางเมื่อคุณแนะนำการแบ่งพาร์ติชันสำหรับตารางของคุณเช่น - คีย์ที่ไม่ซ้ำกันดัชนีเพื่อรวมคอลัมน์พาร์ติชัน ฯลฯ


0

ปีหลังฉันเจอปัญหาเดียวกันกับรุ่น mysql5.7 และ ibdata1 ครอบครอง 150 Gb ดังนั้นฉันจึงเพิ่มการยกเลิกพื้นที่ตาราง

ใช้การสำรองข้อมูล Mysqldump
หยุดบริการ mysql
ลบข้อมูลทั้งหมดจากข้อมูล dir
เพิ่มด้านล่างเลิกทำพารามิเตอร์ tablespace ใน my.cnf ปัจจุบัน

 #undo tablespace
  innodb_undo_directory =  /var/lib/mysql/
  innodb_rollback_segments = 128 
  innodb_undo_tablespaces = 3
  innodb_undo_logs = 128  
  innodb_max_undo_log_size=1G
  innodb_undo_log_truncate = ON

เริ่ม mysql service
store backup mysqldump

ปัญหาได้รับการแก้ไข !!


-1

มีหลายวิธีในการเรียกคืนพื้นที่ว่างหลังจากลบข้อมูลจากตารางสำหรับโปรแกรม MySQL Inodb

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

หากคุณใช้ innodb_file_per_table คุณอาจลอง

  1. หากคุณสามารถลบข้อมูลคำสั่ง truncate ทั้งหมดจะลบข้อมูลและเรียกคืนพื้นที่ว่างให้คุณ
  2. คำสั่งแก้ไขตารางจะวางและสร้างตารางใหม่เพื่อให้สามารถเรียกคืนพื้นที่ว่างได้ ดังนั้นหลังจากลบข้อมูลแล้วให้รัน alter table ที่ไม่ต้องเปลี่ยนอะไรเลยที่จะปล่อย hardisk (เช่น: table TBL_A มี charset uf8 หลังจากลบ data ที่รันแล้ว ALTER TABLE TBL_A charset utf8 -> คำสั่งนี้ไม่มีอะไรเปลี่ยนแปลงจากตารางของคุณ แต่มันทำให้ mysql diskspace
  3. สร้าง TBL_B เช่น TBL_A แทรกข้อมูลเลือกที่คุณต้องการเก็บไว้จาก TBL_A ลงใน TBL_B วาง TBL_A และเปลี่ยนชื่อ TBL_B เป็น TBL_A วิธีนี้มีประสิทธิภาพมากถ้า TBL_A และข้อมูลที่จำเป็นในการลบมีขนาดใหญ่ (คำสั่งลบใน MySQL innodb มีประสิทธิภาพไม่ดีมาก)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.