המרה מ-MyISAM ל-InnoDB: למה זה הכרחי וכיצד לבצע בלי לאבד מידע

MyISAM הוא מנוע אחסון מיושן עם נעילות טבלה ובלי טרנזקציות. כך מבצעים מעבר ל-InnoDB בבטחה.

MyISAM היה מנוע האחסון המוגדר כברירת מחדל ב-MySQL עד גרסה 5.5 (2010). מאז, InnoDB הוא הסטנדרט - וזה לא במקרה. ל-MyISAM יש שלוש מגבלות שהופכות אותו לבחירה בעייתית בכל אתר ייצור: נעילה ברמת טבלה (כל UPDATE/INSERT נועל את כל הטבלה, לא רק את השורה), היעדר טרנזקציות (אם השאילתה נופלת באמצע נשארים נתונים חצי-כתובים), וcrash recovery איטי (דקות עד שעות אחרי קריסת שרת, לעומת שניות ב-InnoDB).

למה זה משנה

בעולם ה-WordPress, נעילת טבלה היא הבעיה המורגשת ביותר. דמיין אתר WooCommerce עם 10 גולשים שמסיימים רכישה במקביל - כל INSERT לטבלת wp_postmeta נועל את כל הטבלה לכמה אלפיות שנייה. שאר הגולשים שמנסים לקרוא ממנה (כל עמוד מוצר!) ממתינים. עומס שמתנהג נורמלית עם InnoDB יכול להפיל אתר MyISAM. בנוסף, גיבויים שכוללים FLUSH TABLES WITH READ LOCK יוצרים זמן השבתה ארוך באתרים גדולים.

ההיעדר של טרנזקציות מסוכן עוד יותר. ב-MyISAM, אם תהליך PHP נופל באמצע פעולה רב-טבלאית (יצירת מנוי שמערבת users + usermeta + posts), נשארים נתונים בלתי-עקביים. WooCommerce, EDD, BuddyPress וכל פלטפורמה רב-שולחנית סובלים. WordPress core עצמו עבר ל-InnoDB כברירת מחדל מ-WordPress 4.0 (2014).

איך לזהות

השאילתה הסטנדרטית מציגה את כל הטבלאות והמנוע שלהן:

SELECT table_name, engine, table_rows,
       ROUND(data_length/1024/1024, 2) AS data_mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY engine, data_mb DESC;

כל שורה עם engine = 'MyISAM' דורשת המרה. במקרים נפוצים תמצא את wp_postmeta או wp_options ב-MyISAM אחרי שדרוג ישן ש-WP בצע בלי להמיר אותן.

איך לתקן

שלב ראשון - גיבוי. לא להמיר בלי גיבוי. mysqldump --single-transaction --routines DBNAME > backup.sql. שלב שני - יצירת רשימה של פקודות ALTER:

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

הדבק את הפלט חזרה ב-SQL והרץ. כל פקודה ALTER יוצרת עותק של הטבלה במנוע החדש ומחליפה את המקורית - זה תהליך כבד שיכול לקחת דקות לטבלאות גדולות. ב-WP-CLI: wp db query "ALTER TABLE wp_options ENGINE=InnoDB;" - מהיר יותר וברור יותר.

שלב שלישי - וידוא שטבלאות עתידיות תיווצרנה ב-InnoDB. ערוך את my.cnf:

[mysqld]
default_storage_engine=InnoDB
innodb_buffer_pool_size=512M

הפעל מחדש את MySQL. אם אין לך גישה ל-my.cnf (shared hosting), בקש מהתמיכה.

טעויות נפוצות

לא להמיר טבלאות עם FULLTEXT index ב-MySQL ישן (לפני 5.6) - InnoDB ישן לא תמך, וההמרה תיכשל. ב-MySQL 5.6+ זה כבר נתמך. שגיאה שנייה: להריץ ALTER במקביל על כמה טבלאות גדולות - זה ממיס את הדיסק. הרץ אחת בכל פעם. שגיאה שלישית: לשכוח להגדיר innodb_buffer_pool_size אחרי המעבר. InnoDB מסתמך על buffer pool בזיכרון לביצועים, וברירת המחדל של 128MB קטנה מדי לרוב האתרים. הגדר ל-50-70% מ-RAM של השרת.

בדיקה לאחר תיקון

הרץ שוב את שאילתת ההצגה - לא צריכה להיות שורה אחת עם MyISAM. הפעל אתר staging ותגרור עומס - עליו להתנהג חלק יותר בכתיבות במקביל. ב-WooCommerce בדוק תהליך checkout במקביל מ-3 דפדפנים - אסור שיהיה lag כפי שהיה ב-MyISAM. בדוק את גודל קבצי ה-DB ב-/var/lib/mysql - InnoDB מאחסן ב-ibdata1 או בקבצי .ibd נפרדים, ואחרי המרה הקבצים החדשים יופיעו.

טיפ: אם אתה עובר מ-MyISAM ל-InnoDB באתר ישן עם הרבה תוספים שכותבים ל-DB, שקול להפעיל גם innodb_flush_log_at_trx_commit=2 זמנית - זה משפר ביצועי כתיבה במחיר של חשיפה קלה לקריסה. אחרי שהמערכת יציבה אפשר להחזיר ל-1.