
שאילתה תקינה, תשובה ריקה - הבאג הנדיר במטמון של Hyperdrive
במהלך הבטא של תמיכת MySQL ב-Hyperdrive, לקוח דיווח על תשובות ריקות במקום שורות נתונים. לפי Cloudflare, התקלה הופיעה בכ-0.001% מהמקרים, ורק כאשר המטמון היה פעיל.
בתחקיר שפרסמה החברה ב-14 באוקטובר 2026 מתואר כיצד הנחה ששימשה במימוש התמיכה ב-PostgreSQL כשלה כשהוחלה על MySQL. מקור התקלה היה באופן שבו Hyperdrive שמר ופירש תשובות במטמון.
האירוע ממחיש קושי בבניית שכבות תשתית: מידע יכול להיות נכון, אך הייצוג שלו עלול להתאים לרכיב אחד ולהטעות רכיב אחר. כשהתנאים האלה נפגשים לעיתים נדירות, גם מערכת שעובדת היטב ברוב המוחלט של הזמן יכולה להסתיר תקלה עקבית.
השכבה שמתווכת בין האפליקציה למסד
Hyperdrive מחבר אפליקציות שפועלות ב-Cloudflare Workers למסדי נתונים. הוא מנהל חיבורים קיימים ומשתמש בהם מחדש, כדי לצמצם את הצורך להקים חיבור מרוחק עבור כל בקשה. הוא יכול גם לשמור תוצאות של שאילתות קריאה מתאימות במטמון.
לשתי הפעולות יש תפקיד שונה. שימוש חוזר בחיבור חוסך את עבודת ההתחברות. שימוש בתוצאה שנשמרה במטמון יכול לחסוך גם את הפנייה למסד ואת ביצוע השאילתה מחדש.
למשל, אפליקציה שמציגה שוב ושוב רשימת כתבות יכולה להסתפק לזמן קצר בתוצאה שכבר התקבלה. לעומת זאת, בדיקת הרשאה או קריאה שצריכה לשקף כתיבה שזה עתה הסתיימה עשויות לדרוש מידע עדכני יותר. תיעוד Hyperdrive מבחין בין שימושים שיכולים לסבול השהיה קצרה בעדכון לבין קריאות שצריכות לעקוף את מטמון השאילתות.
התקלה שנחקרה נגעה לשאלה נוספת: באיזה פורמט נשמרת התוצאה, ומי אמור לדעת לקרוא אותה.
אותן שורות, כללי סיום שונים
תשובת MySQL עוברת ברשת כמבנה מוגדר של חבילות מידע. היא כוללת פרטים על העמודות, את שורות הנתונים וסימנים שמאפשרים לצד המקבל לזהות את גבולות התשובה.
אחת היכולות בפרוטוקול נקראת CLIENT_DEPRECATE_EOF. כאשר היא אינה פעילה, חבילות EOF מסמנות את סוף פרטי העמודות ואת סוף התוצאה. כאשר היא פעילה, סימון הביניים מושמט וסוף התוצאה מסומן באמצעות חבילת OK. המבנה המדויק תלוי ביכולות שהוסכמו בחיבור.
לכן, שתי תשובות יכולות לייצג את אותן שורות נתונים ולהיות שונות ברמת הבתים שנשלחים ברשת. רכיב שקורא תשובה צריך לדעת אילו כללים שימשו ליצירתה. אם הוא מפרש סימן מסוים כסוף התוצאה בזמן שהצד השולח התכוון למשהו אחר, המידע עלול להיקרא באופן שגוי.
זו הסיבה ששמירת ״התוצאה״ במטמון דורשת הגדרה מדויקת: האם נשמר מידע פנימי, או הודעה שכבר הותאמה ללקוח מסוים.
כשהכותב והקורא משתמשים בייצוגים שונים
Hyperdrive מפצל את העבודה בין רכיב Client, הקרוב ל-Worker, לבין Endpoint, הקרוב למסד. כשהם פועלים באותו מרכז נתונים, הם יכולים להשתמש במטמון משותף.
ה-Client שמר תשובות שכבר הותאמו ליכולות של ספריית הלקוח. ה-Endpoint עבד לפי הייצוג הפנימי של Hyperdrive. כאשר רכיב אחד קרא את מה שהשני שמר, אי-ההתאמה בפורמט עלולה הייתה להוביל לתוצאה ריקה או להיתקעות.
התיקון היה לשמור במטמון ייצוג פנימי אחיד של התשובה, לפי יכולות Hyperdrive, ללא תלות ברכיב שכתב אותה.
העיקרון ההנדסי כאן רחב יותר ממסד נתונים מסוים. מטמון משותף הוא גם הסכם בין הכותבים לקוראים שלו. ההסכם צריך להגדיר את משמעות הערך שנשמר, את המבנה שלו ואת השלב שבו מתבצעות התאמות ללקוחות שונים.
מדוע שיעור כשל זעיר עדיין מצדיק חקירה
שיעור של 0.001% שקול לכשל אחד בכל מאה אלף מקרים. לשם המחשה, אם שיעור כזה נשמר לאורך מיליון פעולות דומות, מדובר בכעשרה כשלים. זו המחשה חשבונית של השיעור, ולא נתון נוסף על הלקוח שבדיווח.
בדיקה שמריצה שוב ושוב את המסלול הנפוץ עשויה להצליח בכל פעם. כדי למצוא תקלה שתלויה בשילוב תנאים, צריך לבחון גם את המעברים בין הרכיבים. במקרה של מטמון, שאלות מועילות הן:
- האם כל הרכיבים כותבים את הערך באותו פורמט?
- האם כל קורא יכול לפרש ערך שכתב כל אחד מהכותבים?
- האם המסלול שמחזיר תוצאה מהמטמון שקול למסלול שמקבל אותה מהמקור?
- האם הבדיקה מאמתת את תוכן התשובה, מעבר לכך שהבקשה הסתיימה?
הגישה הזאת רלוונטית גם לבדיקות לפני העלאת קוד שנכתב עם AI לאתר: קוד יכול להיראות סביר בפני עצמו, בעוד שההנחות שלו על רכיבים אחרים דורשות בדיקה נפרדת.
לאחר התיקון דיווחה Cloudflare על היעלמות בעיית התשובות הריקות ועל שיעור הצלחה של 99.99% בחיבורי ה-Client. זהו מדד חיבורים, השונה משכיחות התקלה הנדירה שתוארה בתחילת התחקיר.
במערכת שמתרגמת מידע בין רכיבים, אמינות תלויה גם במה שנשמר בין שתי פעולות תקינות. הגדרה מפורשת של הייצוג המשותף מאפשרת לבדוק את הגבול הזה, במקום להסתמך על כך שכל רכיב יפרש את אותם בתים באותה דרך.