วิธีย่อ / ลบไฟล์ ibdata1 ใน MySQL


561

ฉันใช้ MySQL ใน localhost เป็น "เครื่องมือสืบค้น" สำหรับการแสดงสถิติใน R นั่นคือทุกครั้งที่ฉันเรียกใช้สคริปต์ R ฉันสร้างฐานข้อมูลใหม่ (A) สร้างตารางใหม่ (B) นำเข้าข้อมูลลงใน B ส่งคำค้นหาเพื่อรับสิ่งที่ฉันต้องการจากนั้นฉันปล่อย B และวาง A

มันใช้งานได้ดีสำหรับฉัน แต่ฉันรู้ว่าขนาดไฟล์ ibdata เพิ่มขึ้นอย่างรวดเร็วฉันไม่ได้เก็บอะไรไว้ใน MySQL แต่ไฟล์ ibdata1 มีขนาดเกิน 100 MB แล้ว

ฉันกำลังใช้การตั้งค่า MySQL เริ่มต้นมากขึ้นหรือน้อยลงสำหรับการตั้งค่ามีวิธีที่ฉันสามารถย่อ / ลบไฟล์ ibdata1 โดยอัตโนมัติหลังจากระยะเวลาที่กำหนดหรือไม่


คำตอบ:


777

ที่ibdata1ไม่หดตัวเป็นคุณสมบัติที่น่ารำคาญอย่างยิ่งของ MySQL ibdata1ไฟล์ไม่สามารถจริงจะหดเว้นแต่คุณจะลบฐานข้อมูลทั้งหมดลบไฟล์และโหลดการถ่ายโอนข้อมูล

แต่คุณสามารถกำหนดค่า MySQL เพื่อให้แต่ละตารางรวมถึงดัชนีของมันถูกเก็บไว้เป็นไฟล์แยกต่างหาก ด้วยวิธีibdata1นี้จะไม่เติบโตเป็นจำนวนมาก ตามความเห็นของ Bill Karwinสิ่งนี้ถูกเปิดใช้งานโดยค่าเริ่มต้นตั้งแต่เวอร์ชัน 5.6.6 ของ MySQL

เมื่อไม่นานมานี้ฉันได้ทำสิ่งนี้ อย่างไรก็ตามในการตั้งค่าเซิร์ฟเวอร์ของคุณให้ใช้ไฟล์แยกกันสำหรับแต่ละตารางคุณต้องเปลี่ยนmy.cnfเพื่อเปิดใช้งานสิ่งนี้:

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

ตามที่คุณต้องการเรียกคืนพื้นที่จากที่ibdata1จริงคุณต้องลบไฟล์:

  1. ทำmysqldumpฐานข้อมูลโพรซีเดอร์ทริกเกอร์ ฯลฯทั้งหมดยกเว้นmysqlและและperformance_schemaฐานข้อมูล
  2. ปล่อยฐานข้อมูลทั้งหมดยกเว้นฐานข้อมูล 2 ด้านบน
  3. หยุด mysql
  4. ลบibdata1และib_logไฟล์
  5. เริ่ม mysql
  6. กู้คืนจากการถ่ายโอนข้อมูล

เมื่อคุณเริ่ม MySQL ในขั้นตอนที่ 5 ibdata1และib_logไฟล์จะถูกสร้างขึ้นใหม่

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

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

คุณอาจเคยเห็นสิ่งนี้:
http://bugs.mysql.com/bug.php?id=1341

โดยใช้คำสั่งALTER TABLE <tablename> ENGINE=innodbหรือOPTIMIZE TABLE <tablename>อย่างใดอย่างหนึ่งสามารถดึงข้อมูลและหน้าดัชนีจาก ibdata1 เพื่อแยกไฟล์ อย่างไรก็ตาม ibdata1 จะไม่ย่อขนาดจนกว่าคุณจะทำตามขั้นตอนด้านบน

เกี่ยวกับการinformation_schemaที่ไม่จำเป็นหรือเป็นไปไม่ได้ที่จะลดลง อันที่จริงแล้วเป็นเพียงมุมมองแบบอ่านอย่างเดียวไม่ใช่ตาราง และไม่มีไฟล์ที่เกี่ยวข้องกับไฟล์เหล่านั้นแม้แต่ไดเรกทอรีฐานข้อมูล informations_schemaใช้หน่วยความจำ DB-เครื่องยนต์และมีการปรับตัวลดลงและสร้างใหม่เมื่อหยุด / เริ่มต้นใหม่ของ mysqld ดูhttps://dev.mysql.com/doc/refman/5.7/en/information-schema.html


16
@JordanMagnuson อย่าไปสนใจ data_schema อันที่จริงแล้วเป็นเพียงมุมมองแบบอ่านอย่างเดียวไม่ใช่ตาราง และไม่มีไฟล์ที่เกี่ยวข้องกับพวกเขา ไม่มีแม้แต่ไดเรกทอรีสำหรับฐานข้อมูล informations_schema กำลังใช้หน่วยความจำ db-engine และถูกดร็อปและสร้างใหม่เมื่อหยุด / รีสตาร์ทของ mysqld ดูdev.mysql.com/doc/refman/5.5/en/information-schema.html เกี่ยวกับ performance_schema ฉันไม่ได้ใช้สคีมานั้นเอง
John P

4
ฉันไม่รู้ว่านี่เป็นสิ่งล่าสุดหรือไม่ แต่เมื่อตัวเลือก innodb_file_per_table ถูกเปิดใช้งานคุณสามารถเรียกใช้ "ALTER TABLE <tablename> ENGINE = InnoDB" (แม้จะเป็น InnoDB แล้ว) และมันจะย้ายตารางไปยังไฟล์ของแต่ละคน . ไม่จำเป็นต้องวางฐานข้อมูลและอื่น ๆ
ซีอาร์

3
+1 FWIW, MySQL 5.6 เปิดใช้งานinnodb_file_per_tableตามค่าเริ่มต้น
Bill Karwin

3
ใช่ ibdata1 คาดว่าจะปรากฏพร้อมกับไฟล์อื่น ๆ ไฟล์ ibdata1 จะยังคงเก็บข้อมูลเมตาเกี่ยวกับตารางการเลิกทำบันทึกและบัฟเฟอร์
John P

1
ฉันไม่มีที่ว่างในเซิร์ฟเวอร์เนื่องจากไฟล์ ibdata1 ดังนั้นฉันจึงไม่สามารถถ่ายโอนฐานข้อมูลได้ มันจะเหมือนกันไหมที่จะย้ายไฟล์ไปที่ / var / lib / mysql (ยกเว้น "mysql", "ibdata1", "ib_logfile0" และ "ib_logfile1") จากนั้นทำตามขั้นตอนหรือไม่ ดูstackoverflow.com/questions/2482491/…
Sophivorus

47

การเพิ่มคำตอบที่จอห์นพี ,

สำหรับระบบ linux สามารถทำขั้นตอนที่ 1-6 ได้ด้วยคำสั่งเหล่านี้:

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. sudo /etc/init.d/mysqld stop
  4. sudo rm /var/lib/mysql/ibdata1
    sudo rm /var/lib/mysql/ib_logfile (และลบของ ib_logfile อื่น ๆ ที่อาจจะตั้งชื่อib_logfile0, ib_logfile1ฯลฯ ... )
  5. sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

คำเตือน: คำแนะนำเหล่านี้จะทำให้คุณสูญเสียฐานข้อมูลอื่น ๆ ถ้าคุณมีฐานข้อมูลอื่น ๆ ในอินสแตนซ์ mysql นี้ ตรวจสอบให้แน่ใจว่ามีการปรับเปลี่ยนขั้นตอนที่ 1,2 และ 6,7 เพื่อครอบคลุมฐานข้อมูลทั้งหมดที่คุณต้องการเก็บไว้


6
คุณต้องทำซ้ำ 1,2 และ 6 สำหรับทุกฐานข้อมูลที่มีตาราง InnoDB
มาร์ควิสแห่ง Lorne

4
คุณต้องการอีกสองสามขั้นตอนในระหว่าง # 5 ถึง # 6 คุณต้องสร้างฐานข้อมูลและกำหนดสิทธิ์ใหม่อีกครั้ง ดังนั้นจากคำสั่งไคลเอนต์ mysql create database database_name;แล้วgrant all privileges on database_name.* to 'username'@'localhost' identified by 'password';
เฟรด

1
@ เฟรดฉันไม่จำเป็นต้องให้สิทธิ์พิเศษเมื่อทำสิ่งนี้ อาจเป็นเพราะฉันสร้างฐานข้อมูลใหม่ด้วยชื่อเดียวกันหรือไม่
crmpicco

2
หากต้องการพิมพ์รหัสผ่านที่Password:พรอมต์ (ซึ่งเป็นวิธีปฏิบัติที่ปลอดภัยกว่า) เพียงแค่ใส่-pรหัสผ่านจริง ๆ
ADTC

ทริกเกอร์เหตุการณ์และกิจวัตร / ฟังก์ชั่นจะไม่ถูกทิ้งเว้นแต่คุณจะบอก mysqldump ให้ทำเช่นนั้น เพิ่ม - ทริกเกอร์ - กิจกรรมและ - รูทีนด้วยหากฐานข้อมูลใด ๆ ของคุณมีอยู่ นอกจากนี้เพียงแค่ถ่ายโอนข้อมูลด้วย - ทั้งหมด - ฐานข้อมูลเพื่อถ่ายโอนฐานข้อมูลทั้งหมดในคราวเดียวแทนที่จะเป็นหนึ่งต่อหนึ่ง
Friek

34

เมื่อคุณลบตาราง innodb MySQL จะไม่เพิ่มพื้นที่ว่างภายในไฟล์ ibdata นั่นคือสาเหตุที่ทำให้พื้นที่เติบโตขึ้นเรื่อย ๆ ไฟล์เหล่านี้แทบจะไม่หด

วิธีย่อขนาดไฟล์ ibdata ที่มีอยู่:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

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

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

ข้อมูลเพิ่มเติมเกี่ยวกับหลายพื้นที่ตาราง:

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html


ลิงค์แรกเสียการจับคู่ที่ใกล้เคียงที่สุดที่ฉันหาได้: dev.mysql.com/doc/refman/5.5/en/…
BlackICE

14

หากคุณใช้เครื่องมือจัดเก็บข้อมูล InnoDB สำหรับ (บางส่วน) ตาราง MySQL ของคุณคุณอาจพบปัญหากับการกำหนดค่าเริ่มต้นแล้ว ดังที่คุณอาจสังเกตเห็นในไดเรกทอรีข้อมูล MySQL ของคุณ (ใน Debian / Ubuntu - / var / lib / mysql) อยู่ที่ไฟล์ชื่อ 'ibdata1′ มันเก็บข้อมูล InnoDB เกือบทั้งหมด (ไม่ใช่บันทึกธุรกรรม) ของอินสแตนซ์ MySQL และอาจมีขนาดค่อนข้างใหญ่ โดยค่าเริ่มต้นไฟล์นี้มีขนาดเริ่มต้น 10Mb และจะขยายโดยอัตโนมัติ น่าเสียดายที่การออกแบบไฟล์ข้อมูล InnoDB ไม่สามารถลดขนาดลงได้ นั่นเป็นเหตุผลที่ DELETE TRUNCATEs DROPs ฯลฯ จะไม่เรียกคืนพื้นที่ที่ใช้โดยไฟล์

ฉันคิดว่าคุณสามารถหาคำอธิบายและวิธีแก้ปัญหาที่ดีได้ที่นั่น:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/


11

สคริปต์โพรซีเดอร์ของคำตอบที่ยอมรับในสคริปต์อย่างรวดเร็ว:

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

บันทึกเป็นpurge_binlogs.shและเรียกใช้เป็นrootและเรียกเป็น

ไม่รวมmysql, information_schema, performance_schema(และbinlog directory)

สมมติว่าคุณมีบัญชีผู้ดูแลระบบใน/root/.my.cnfและฐานข้อมูลของคุณอยู่ในค่าเริ่มต้น/var/lib/mysqlไดเรกทอรี

นอกจากนี้คุณยังสามารถล้างบันทึกไบนารีหลังจากใช้งานสคริปต์นี้เพื่อคืนพื้นที่ว่างในดิสก์ด้วย:

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;

ยังไม่แน่ใจว่าทำไม แต่วันนี้บางตาราง InnoDB ของฉันเกิดความเสียหายในระหว่างกระบวนการที่คล้ายกันดังนั้นฉันจะไม่ลบalldatabases.sqlก่อนที่จะตรวจสอบอีกครั้งหากตารางทั้งหมดแข็งแรง สำหรับการปรับปรุงบางอย่าง: ตั้งค่าinnodb_fast_shutdown=0ก่อนปิดเครื่องให้ตั้งค่าautocommit=0ก่อนนำเข้าไฟล์ SQL ดำเนินการCOMMITและตั้งค่าautocommit=1หลังจากนำเข้าไฟล์ SQL ใช้mysqlcheck --all-databasesก่อนที่จะลบข้อมูลสำรอง
Victor

6

หากเป้าหมายของคุณคือการตรวจสอบพื้นที่ว่างของ MySQL และคุณไม่สามารถหยุด MySQL เพื่อลดขนาดไฟล์ ibdata ของคุณให้รับมันผ่านคำสั่งสถานะตาราง ตัวอย่าง:

MySQL> 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

จากนั้นเปรียบเทียบค่านี้กับไฟล์ ibdata ของคุณ:

du -b ibdata1

ที่มา: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html


4

ในรุ่นใหม่ของสูตรเซิร์ฟเวอร์ mysql ด้านบนจะบดขยี้ฐานข้อมูล "mysql" ในรุ่นเก่ามันใช้งานได้ ในบางตารางจะเปลี่ยนเป็นประเภทตาราง INNODB และการทำเช่นนั้นคุณจะเกิดความเสียหาย วิธีที่ง่ายที่สุดคือ:

  • ถ่ายโอนฐานข้อมูลทั้งหมดของคุณ
  • ถอนการติดตั้ง mysql-server
  • เพิ่มใน my.cnf ยังคงอยู่:
    [mysqld]
    innodb_file_per_table=1
  • ลบทั้งหมดใน / var / lib / mysql
  • ติดตั้ง mysql-server
  • คืนค่าผู้ใช้และฐานข้อมูล

1

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

การใช้ autoextend (อาจเป็นการตั้งค่าขนาดที่ธรรมดาที่สุด) ibdata1 จัดเก็บข้อมูลล่วงหน้าล่วงหน้าซึ่งจะเพิ่มขึ้นทุกครั้งที่มันเกือบเต็ม ทำให้การเขียนเร็วขึ้นเนื่องจากจัดสรรพื้นที่ไว้แล้ว

เมื่อคุณลบข้อมูลจะไม่ย่อขนาด แต่พื้นที่ภายในไฟล์ถูกทำเครื่องหมายว่าไม่ได้ใช้ ตอนนี้เมื่อคุณแทรกข้อมูลใหม่มันจะใช้พื้นที่ว่างในไฟล์ก่อนที่จะขยายไฟล์อีกต่อไป

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


66
ฉันคิดว่าคุณไม่สนใจที่จะเพิ่มพื้นที่ว่าง
ดึง

2
ฉันมีพาร์ติชัน Solid State 60Gig ฉันหมดพื้นที่อย่างรวดเร็วเนื่องจากฉันทำงานกับฐานข้อมูล 4 + กิก ฉันกำลังจะย้าย mysql ไปยังพาร์ติชันอื่นในไม่ช้า แต่คำถามนี้และคำตอบของมันจะช่วยฉันในระหว่างนี้
NullVoxPopuli

3
ขอบคุณสำหรับคำตอบนี้มีประโยชน์มาก ฉันล้างตารางบางส่วนออกจากข้อมูลดั้งเดิม ... มันเป็นการดีที่จะรู้ว่าขนาดของดิสก์จะไม่เพิ่มขึ้นอีกในเร็ว ๆ นี้
แบรด

1
ฉันมีไฟล์ ibdata1 500G - แต่ข้อมูลเกือบทั้งหมดที่เก็บไว้ในนั้นจะถูกเก็บไว้ในไฟล์ต่อฐานข้อมูล ฉันต้องการมากที่จะหดพื้นที่ว่างเปล่าที่ใหญ่โตนี้!
frankster

2
เรื่องไร้สาระสมบูรณ์! ไฟล์ที่ช่วยให้ท้องอืดขึ้นจะต้องมีการตัดแต่งไม่ว่าคุณจะทำงานออกจากพื้นที่หรือไม่ storage leakฉันจะเรียกมันว่า
ADTC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.