แถวขาดหายไปหลังจากการแปลงออนไลน์จาก MyISAM เป็น InnoDB


16

เรามีฐานข้อมูลขนาดเล็กพอสมควรที่เราต้องการแปลงจาก MyISAM เป็น InnoDB ในฐานะที่เป็น noobs ของฐานข้อมูลเราเพิ่งแปลง (โดยใช้ตารางแก้ไข) โดยไม่ทำให้เว็บไซต์ล้มเหลว

ตอนนี้การแปลงเสร็จสิ้นแถวจำนวนมากเป็นระยะ ๆ ดูเหมือนจะหายไป อาจเป็นเพราะการดำเนินการระหว่างการแปลงหรือไม่ หรือเป็นปัญหาที่อื่น?


ตารางใดหายไปแถว คนที่คุณแปลงหรือตารางอื่น ๆ ?
longneck

คำตอบ:


20

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

เมื่อแก้ไขสคีมาที่มีอยู่หรือทำสิ่งใดที่อาจส่งผลต่อข้อมูลนี่คือคำแนะนำพื้นฐาน:

  1. ทำการสำรองข้อมูลก่อน
  2. มีแผนการเปลี่ยนแปลง
  3. ทดสอบแผนของคุณกับโฮสต์ออฟไลน์
  4. มีแผนการทดสอบเพื่อเปรียบเทียบข้อมูลก่อนและหลัง
  5. กำหนดเวลาและหยุดทำงาน
  6. ทำการสำรองและสแน็ปช็อตทันทีหลังจากการหยุดทำงานของคุณมีผลและคุณยืนยันว่าทราฟฟิกหยุดทำงาน
  7. หากคุณใช้ MYISAM ให้ใช้ 'ตารางตรวจสอบ' เพื่อประเมินสิ่งที่คุณกำลังทำอยู่ก่อนที่คุณจะแก้ไข
  8. คัดลอกตารางในเครื่องนอกเหนือจากการสำรองข้อมูลของคุณในกรณี
  9. ดำเนินการต่อด้วยความระมัดระวังเปิดใช้ "- แสดงคำเตือน" และเอาท์พุทอื่น ๆ เพื่อให้คุณมีภาพเต็มเมื่อคุณทำการเปลี่ยนแปลง
  10. หากข้อมูลมีความสำคัญต่อคุณให้จ้าง DBA แม้เพียงเพื่อขอคำปรึกษาในระหว่างการโยกย้ายดังนั้นคุณจึงมีประสบการณ์ช่ำชองอยู่เคียงข้างคุณ

อาจมีอีกมากมายที่ฉันสามารถเข้าไป แต่ข้างต้นจะให้ตัวเลือกแก่คุณเมื่อมีบางอย่างผิดปกติ

เท่าที่ข้อมูล / แถวที่หายไปของคุณไม่มีทางรู้ว่า w / oa "ก่อน / หลัง" ภาพรวมเพื่อเปรียบเทียบ คุณสามารถเปรียบเทียบกับข้อมูลสำรองล่าสุดของคุณเป็นอย่างน้อยตรวจสอบว่ามาก


ฉันอ่านสิ่งนี้ แผน DR ที่ดี คำตอบของคุณจะได้รับ +1 สำหรับการตอบคำถามที่อ่อนไหวยิ่งกว่าที่ฉันได้รับนอกเหนือจากการวางแผนล่วงหน้า
RolandoMySQLDBA

1
@randy ทำเครื่องหมายว่าเป็นคำถามโปรดเนื่องจากคำตอบที่ดีของคุณ
techExplorer

8

หนึ่งในวิธีที่ดีที่สุดในการแปลง MyISAM เป็น InnoDB โดยไม่ต้องหยุดทำงานทั้งหมดมีเพียงหนึ่งสิ่งที่จำเป็นต้องมี: ใช้ Replication Slave

นี่คือมุมมองตานกของแผน

  1. สร้างการตั้งค่าการจำลองแบบ Master / Slave
  2. แปลงทุกตาราง MyISAM บนสลาฟเป็น InnoDB
  3. ชี้แอปของคุณไปที่ Slave

ฟังดูง่าย? มีรายละเอียดมากมายหลังนี้

สร้างการตั้งค่าการจำลองแบบ Master / Slave

มีวิธีที่ลื่นไหลในการสร้าง Slave โดยไม่รบกวนอาจารย์มากนัก ฉันเขียนสองโพสต์:

แทนที่จะอ่านรายละเอียดวิธีใช้ rsync โปรดอ่านทั้งสองโพสต์

แปลงทุกตาราง MyISAM บนสลาฟเป็น InnoDB

บน DB Slave คุณสามารถใช้คำสั่ง SQL ต่อไปนี้:

สำหรับ MySQL 5.5:

SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM' AND table_schema NOT IN
('information_schema','mysql','performance_schema');

เวอร์ชันสำหรับ MySQL ก่อน MySQL 5.5

SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM' AND table_schema NOT IN
('information_schema','mysql');

การใช้เอาต์พุตจากเคียวรีคุณมีสคริปต์การแปลงสำหรับสลาฟ

คุณต้องใส่สองบรรทัดนี้ที่ด้านบนสุดของสคริปต์:

SET SQL_LOG_BIN = 0;
STOP SLAVE;

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

นี่คือวิธีการสร้างสคริปต์และเรียกใช้งาน:

SQLSTMT="SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') FROM information_schema.tables WHERE engine = 'MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema')"
INNODB_CONV_SCRIPT=MassConvertMyISAMTablesToInnoDB.sql
echo "SET SQL_LOG_BIN = 0;" > ${INNODB_CONV_SCRIPT}
echo "STOP SLAVE;" >> ${INNODB_CONV_SCRIPT}
mysql -h(IP of Master) -u... -p... --skip-column-names -A -e"${SQL}" >> ${INNODB_CONV_SCRIPT}
echo "START SLAVE;" >> ${INNODB_CONV_SCRIPT}
mysql -h(IP of Slave) -u... -p... --skip-column-names -A < ${INNODB_CONV_SCRIPT}

ชี้แอปของคุณไปที่ Slave

ทำการเลือกคิวรีจาก Slave หากคุณพอใจกับเนื้อหาข้อมูลบน Slave คุณสามารถชี้แอปของคุณไปยัง Slave ได้ดังนี้:

  1. บน Slave ให้เรียกใช้SHOW SLAVE STATUS\Gและตรวจสอบให้แน่ใจว่า Seconds_Behind_Master เป็น 0
  2. บน Slave, mysqldump -h (IP of Slave) -u ... -p ... - Single-transaction - รูทีน - triggers - all-database> MySQLBackup.sql (เฮ้การสำรองข้อมูลจะดี เกี่ยวกับตอนนี้)
  3. บนมาสเตอร์ให้เรียกใช้service mysql stop(การหยุดทำงานเริ่มต้น)
  4. ทำซ้ำขั้นตอนที่ 1
  5. ชี้แอปของคุณไปที่ Slave (การหยุดทำงานจะสิ้นสุดลงในการเชื่อมต่อครั้งแรกของแอพ)

หากคุณมาถึงจุดนี้โดยไม่ได้รับบาดเจ็บขอแสดงความยินดี !!!

โบนัสเพิ่ม : ถ้าคุณตั้งค่าการจำลองแบบหลัก / การจำลองแบบหลัก (หรือการจำลองแบบวงกลม) แทนการเป็นแบบ Master / Slave คุณสามารถทำสิ่งนี้แทน:

  1. บน Slave ให้เรียกใช้SHOW SLAVE STATUS\Gและตรวจสอบให้แน่ใจว่า Seconds_Behind_Master เป็น 0
  2. บน Slave, mysqldump -h (IP of Slave) -u ... -p ... - Single-transaction - รูทีน - triggers - all-database> MySQLBackup.sql (เฮ้การสำรองข้อมูลจะดี เกี่ยวกับตอนนี้)
  3. ชี้แอปของคุณไปที่ Slave (การหยุดทำงานเริ่มต้นและสิ้นสุดในการเชื่อมต่อครั้งแรกของแอป)
  4. ใน Master ใหม่ให้เรียกใช้ STOP SLAVE;
  5. ใน Master ใหม่ให้เรียกใช้ CHANGE MASTER TO MASTER_HOST='';

สิ่งที่คุณมีตอนนี้คือ Master / Slave ในสิ่งที่ตรงกันข้าม New Master มีข้อมูล InnoDB และ Master เก่าเป็นทาสของข้อมูล MyISAM หากคุณแบ่งการอ่านและเขียนการอ่านสามารถไปจาก Slave (การอ่านนั้นเร็วกว่าจาก MyISAM กว่า InnoDB) และการเขียนไปที่ Master (การสนับสนุนการทำธุรกรรมสำหรับ InnoDB) เช่นเดียวกับฮันนาห์มอนทานาร้องเพลงคุณจะได้รับสิ่งที่ดีที่สุดของโลกทั้งสอง (ใช่ฉันมีลูกสาวสองคนที่รักการแสดง) !!!

โบนัสเพิ่มอีก : เนื่องจากอาจารย์คือตอนนี้ InnoDB คุณสามารถทำ mysqldump จากท่านอาจารย์โดยไม่ต้องหยุดทำงานและไม่รบกวนการทำธุรกรรม ข้อเสียเปรียบเท่านั้นคือเพิ่ม CPU และดิสก์ I / O คุณสามารถใช้ mysqldump ของโครงสร้างตารางบน Master (InnoDB) และ mysqldump ของข้อมูลบน slave เท่านั้น (การดัมพ์ดังกล่าวจะไม่มีการอ้างอิงถึง InnoDB หรือ MyISAM มันจะเป็น data) บวกกับ mysqldump ของ โครงสร้างตารางสำหรับทาสที่มีเค้าโครง MyISAM

ความเป็นไปได้สามารถดำเนินต่อไปได้เนื่องจากการตั้งค่าใหม่นี้ ...

อัพเดท 2011-08-27 19:50 EDT

ขอโทษด้วย. ฉันไม่ได้อ่านคำถามทั้งหมด คุณดำเนินการ converseion ที่มีอยู่แล้ว

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

  • กู้คืน / var / lib / mysql ไปยังตำแหน่งอื่นเช่น / var / lib / mysql2
  • วิ่ง service mysql stop
  • วิ่ง service mysql start --datadir=/var/lib/mysql2
  • mysqldump ฐานข้อมูลจากข้อมูลสำรองนั้นไปยัง /root/olddata.sql
  • รัน mysqlbinlog เทียบกับการบันทึกไบนารีทั้งหมดใน / var / lib / mysql (ไม่ใช่ / var / lib / mysql2) จากจุดเริ่มต้นตั้งแต่การสำรองข้อมูลครั้งล่าสุดลงใน /root/changes.sql
  • โหลด changes.sql ไปที่ mysql (เนื่องจากยังคงชี้ไปที่ / var / lib / mysql2)

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

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