עומס יתר של חיבורים: מתי ProxySQL הכרחי
אפליקציה ממעטת לחסוך בחיבורים: תרחיש טיפוסי — לפתוח חיבור לשאילתה אחת או שתיים ולסגור. כל עוד יש עשרות פניות, זה לא מורגש; בשיא יש מאות, והמסד נתקל במגבלת החיבורים.
משם מתחילה שרשרת: חלק מהניסיונות נדחים, חלק נכנסים לתור בצד השרת, האפליקציה חוזרת על פניות שכשלו ומביאה למיצוי המגבלה סופית.
זמן התגובה במצב כזה גדל לא באופן לינארי, אלא בקפיצות. כל עוד יש מטפל פנוי, התגובה יציבה; מעבר לסף התור גדל מהר יותר מהתעבורה שמגיעה, והאחוזון ה-95 עולה פי כמה כשהחציון כמעט לא משתנה — בגרף זה נראה כ"מסד הנתונים פתאום הפך איטי".
צוואר הבקבוק במקרה זה אינו במעבד ולא בדיסק, אלא ביצירה מחדש מתמדת של חיבורים: כל אחד צורך תיאום, בדיקת הרשאות והקצאת סשן.
מאגר מקומי בתוך האפליקציה לא פותר את הבעיה: בסקייל אופקי עותקי השירותים מכפילים מאגר משלהם, והמגבלה שוב קרובה. כאן נדרש ProxySQL — שכבה בין האפליקציה למסד הנתונים.
הוא מחזיק חיבורים ארוכי חיים לשרת, מחזיר ללקוחות חיבורים מוכנים, מפריד בין קריאה לכתיבה, מגביל ניסיונות חוזרים, ובמקום לדחות מכניס את השאילתה לתור עם מגבלת המתנה צפויה.
ההגדרה עצמה אינה מסתכמת בהתקנה: יש צורך בכללי ניתוב, פסקי זמן, גדלי מאגרים לפי פרופיל העומס ומטריקות שמראות שהמגבלה התרחקה. להלן נסביר כיצד מטפלים בכך.
מה נותן לאפליקציה מאגר חיבורים מנוהל
כל תהליך עבודה של האפליקציה מחזיק חיבור משלו למסד הנתונים. כל עוד יש עשרות מהם, זה לא מורגש. ברגע שמבצעים סקייל לאפליקציה לעומס שיא, מספר התהליכים נתקל בתקרת החיבורים: בקשות ממתינות לפתיחת ערוץ, וזנב ההשהיות גדל מהר יותר מהתעבורה.
מאגר חיבורים מנוהל מסיר את הצימוד הזה. שכבת ביניים מקבלת אלפי חיבורי לקוח ומבצעת ריבוב שלהם למספר קטן של חיבורים קבועים לשרתי מסד הנתונים: 2000 נכנסים מתמפים ל-40 יוצאים.
האפליקציה מפסיקה להיות תלויה במגבלה על מספר התהליכים — בשיא עולה התפוקה, וזמן התגובה היציב נשאר באותם גבולות כמו בעומס רגוע.
פורסים את ProxySQL ומגדירים כללי ניתוב: קריאות עוברות לרפליקות, כתיבה — למאסטר, וחיבורים עוברים שימוש חוזר בין שאילתות. זמינות הצמתים נבדקת כל העת, לכן מעבר בעת כשל אורך שניות ואינו דורש התערבות בקוד האפליקציה.
חיבורי לקוח לא נקטעים בעת תקלה קצרה בצומת — חיבור מחדש מבצע המאגר, לא האפליקציה, ושגיאות זמניות לא מגיעות למשתמש. את האפקט מאמתים במטריקות: שיעור הבקשות שטופלו בלי המתנה לחיבור, זמן תגובה לפי אחוזונים לפני ואחרי השיא, עומק התור ומספר המעברים בעת כשל.
השוואה בין מצבי ניתוב בקשות
ניתוב קריאה וכתיבה נפתר באחד מארבעה רבדים — משכבת ביניים לפני מסד הנתונים ועד בחירה מפורשת של חיבור בקוד. הרובד קובע היכן נמצאת הלוגיקה של הפרדת התעבורה וכמה קוד יהיה צריך לשנות כשהטופולוגיה משתנה. להלן תנאי ההתאמה והמגבלות של כל אפשרות.
שכבת ביניים כמו ProxySQL עומדת בין האפליקציה למסד הנתונים: האפליקציה רואה כתובת אחת, והשכבה מחזיקה מאגר, עוקבת אחר מצב הצמתים ומפרידה בעצמה בין קריאה לכתיבה. זהו מסלול עם מינימום שינויים בקוד, כאשר יש כמה שירותים והשפות שונות.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| שכבת ביניים לפני מסד הנתונים | כמה אפליקציות ושפות, נדרש מאגר משותף והפרדת קריאה וכתיבה בלי שינויים בקוד | נקודת כשל נוספת וקטע רשת מיותר, נדרשים ניטור, עדכונים ומלאי חיבורים משלהם |
| מאגר מובנה באפליקציה | שירות אחד עם עומס צפוי, המאגר חי במסגרת התהליך | בסקייל מספר החיבורים גדל בכפולות, מגבלות מסד הנתונים מחושבות ידנית, כשל צומת מטופל בקוד |
| מאגר בצד הדרייבר | האפליקציה כבר עובדת ישירות עם מסד הנתונים, נדרשים שימוש חוזר בחיבורים ובדיקת זמינות | הדרייבר לא מבצע ניתוב קריאה וכתיבה, ומעבר בעת כשל צומת נשאר באפליקציה |
| הקצאה ידנית | משימות חד-פעמיות: מיגרציות, דוחות, ייצוא לצומת מסוים | לא מתרחב, הלוגיקה מתפזרת בקוד, טעות בבחירת הצומת נראית רק בעומס אמיתי |
בפועל משלבים בין האפשרויות: שכבת ביניים מחזיקה מאגר משותף והפרדת תעבורה, מאגר מובנה מחליק קפיצות בתוך התהליך. הקצאה ידנית נשארת לעבודות חד-פעמיות — כחריג, לא כתבנית קבועה.
כיצד אנו מטמיעים מאגר חיבורים: שלבי העבודה
ProxySQL לפני מסד הנתונים — זה לא "התקנו ושכחנו". סדר העבודות קובע אם מסד הנתונים יעבור את השיא בלי גידול בשגיאות ובלי שינויים בקוד האפליקציה. טעות ברצף כמעט תמיד מתגלה בפרודקשן: המאגר קיים, אבל החיבורים עדיין נתקלים במגבלת הצומת הראשי. להלן כיצד אנו בונים את העבודה.
-
איסוף מטריקות ופרופיל עומס. משרתי פרודקשן אוספים סטטיסטיקה: כמה חיבורים נפתחים וכמה זמן הם חיים, אילו שאילתות דומיננטיות, היכן זמן ההמתנה גדל. זה בסיס להשוואת "לפני ואחרי" — בלעדיו ההגדרה הופכת לניחוש.
-
תכנון סכימת הניתוב. קובעים מה עובר לצומת הראשי, מה לרפליקות וכיצד האפליקציה מתנהלת אם רפליקה מפגרת. נקודות הכשל וסדר המעבר מתעדים בסכימה מראש.
-
הגדרת המאגר וכללי שכתוב שאילתות. מגדירים גבולות מאגר לפי משתמש ומסד נתונים, זמן חיים של חיבורים, מספר חיבורי שרת לכל חיבור לקוח. כללי השכתוב מביאים שאילתות שונות לצורה אחת — שיעור הפגיעות במטמון עולה, והעומס על השרתים יורד.
-
בדיקה תחת עומס. חוזרים על פרופיל מהשלב הראשון בסביבת בדיקות, ובנפרד מפילים צומת: בודקים כמה מהר הניתוב מתארגן מחדש ואם מספר השגיאות באפליקציה עולה. את הכללים מתקנים לפי מספרים, לא לפי תחושות.
-
העלאה לפרודקשן. מפעילים בהדרגה — תחילה חלק מהתעבורה, אחר כך הכול, תוך מעקב אחר השהיות ומספר החיבורים. מסלול כיבוי נשאר: אפשר להחזיר את התעבורה ישירות אם המטריקות יחרוגו מהגבולות.
-
מסירה והדרכה. מוסרים קונפיגורציות, סכימה, כללים וניתוח סטטיסטיקה: כיצד לקרוא את מצב המאגר ומה לשנות כשהעומס גדל. הצוות צריך להוסיף כלל בעצמו או להרחיב את המאגר.
מדיניות גישה, קונפיגורציות ותקנות
לפני העלאת מאגר החיבורים לפרודקשן הלקוח מקבל חבילת ארטיפקטים שלפיה אפשר לתחזק את המערכת, למסור בין משמרות ולשחזר לאחר כשל. להלן מינימום חובה: בלעדיו פרוקסי ProxySQL מתקיים על תיקונים ידניים ברגע האירוע.
- קובצי קונפיגורציה. קונפיגורציה ראשית ודריסות לפי צדדים אחוריים, מסודרות לפי סביבות ותחת בקרת גרסאות, עם תיאור: איזה פרמטר אחראי למה ומה ישתנה כשמתקנים אותו.
- סכימות זרימה. מסלול הבקשה מהאפליקציה דרך הפרוקסי עד הרפליקות: כללי הפרדת קריאה וכתיבה, ניתוח שאילתות, התנהגות בעת כשל צומת.
- חשבונות והרשאות. משתמשים נפרדים לאפליקציה, לניטור ולניהול, הרשאות מינימליות נדרשות, קישור לכללי ניתוב; סודות — במאגר סודות, לא בקובץ על הדיסק.
- מגבלות חיבורים. גבולות למאגר, למשתמש, למארח ולקצה האחורי עם נימוק לכל אחד: באיזה תרחיש הוא מושג וכיצד המערכת ממשיכה להתדרדר.
- מדיניות גישה. מי ומאילו רשתות נכנס לממשק הניהולי, מה חל על בקשות לקוח, ומה מגן על ההיקף החיצוני.
- נוהל תחזוקה ותורנות. סדר תיקון כללים ומגבלות, טעינה מחדש של קונפיגורציה בלי לקטוע חיבורים חיים, חלונות עבודה, נקודות שחזור והוראות לתורן: מה לבדוק ומה לעשות ראשון.
את המסמכים מעדכנים יחד עם הקונפיגורציה — בשינוי הטופולוגיה הבא לא משחזרים את הלוגיקה מהזיכרון.
מקרה בוחן: כיצד עלתה התפוקה של מסד הנתונים
שירות עם זרימה לא אחידה: בשעות שיא בבוקר ובערב מספר הפניות במקביל למסד הנתונים גדל פי כמה, וביניהן העומס ירד כמעט לאפס. כל תהליך עבודה החזיק חיבור משלו ל-MySQL, והאפליקציה נתקלה בתקרה על מספרם: לא ניתן היה להוסיף תהליכים — מסד הנתונים החל להתדרדר בכל הבקשות בבת אחת.
לפני: זמן התגובה גדל יחד עם העומס
בשעות שיא זמן התגובה באחוזון ה-95 גדל פי שלושה לעומת שעות רגועות, חלק מהשאילתות נכנסו לפסק זמן. סוג הכשל העיקרי — החיבורים נגמרו, בקשות חדשות נכנסו לתור ונפלו עם שגיאת הקמת קשר. התפוקה גדלה יחד עם מספר התהליכים רק עד נקודה מסוימת, ומשם גדל רק זמן התגובה.
אחרי: קו ישר בשיא
בין האפליקציה למסד הנתונים עמד ProxySQL — שכבת פרוקסי עם מאגר חיבורים משלה, שמשתמשת בהם מחדש בין תהליכי עבודה. כללי הניתוב הפרידו בין קריאה לכתיבה, שאילתות אנליטיות עברו לרפליקה, ובדיקת תקינות הוציאה צומת בעייתי מהסבב לפני שהצטברו בו שגיאות.
זמן התגובה בשעות שיא הפסיק להתרחק מהעומס: קו האחוזון ה-95 נעשה ישר וקרוב לזה של שעות רגועות. התפוקה גדלה פי כמה על אותה חומרה, תקרת מספר התהליכים הוסרה, וכשלים מסוג "החיבורים נגמרו" לא חזרו עוד בתצפיות.
במה ProxySQL שונה ממאגר בתוך האפליקציה
מאגר מובנה חי בתוך תהליך האפליקציה: חיבורים נפתחים בבקשה הראשונה, חוזרים למאגר מקומי ומשמשים מחדש בקריאה הבאה. כל עוד יש שירות אחד, זה מספיק — עלויות ההקמה של חיבור לא חוזרות על עצמן בכל בקשה.
הבעיה מתחילה בסקייל אופקי: כל עותק של האפליקציה מחזיק מאגר משלו, ומספר החיבורים למסד הנתונים גדל עם מספר העותקים, לא עם העומס האמיתי.
שכבה נפרדת לפני מסד הנתונים משנה את הסכימה. האפליקציה כבר לא מחזיקה חיבורים ארוכי חיים — היא מספקת סשנים קצרים, ואת החיבורים המשותפים לשרת מסד הנתונים מתחזק צומת ביניים עם גודל מאגר קבוע.
עשרה עותקים של השירות וצומת אחד נותנים מספר חיבורים צפוי, שאינו תלוי בכמה מופעים הרמתם באותו רגע. בד בבד נפתרת הכאב עם הפעלות מחדש: בעדכון האפליקציה החיבורים למסד הנתונים לא נקטעים ולא נוצרים מחדש במפולת.
ההבדל השני — אי-תלות בשפה. מאגר מובנה מוגדר באמצעים של ספריית גישה לנתונים מסוימת, ולכל סטאק יש פרמטרים משלו, פסקי זמן משלו והתנהגות משלו בעת ניתוק. שכבת ביניים עומדת ברמת הרשת, לכן שירותים בשפות שונות עוברים דרך אותו פתח עם אותם כללים.
השלישי — נקודת כללים אחת. ניתוב קריאה לרפליקות, קטיעת שאילתות ארוכות, עדיפות למשימות רקע, הגבלת תדירות פניות — הכול מתואר בקובץ קונפיגורציה אחד, ולא משוכפל בקוד של כל שירות. זה מקל באופן ניכר על ניתוח אירועים: רואים של מי הבקשה ולאן עברה.
מסקנה מעשית: מאגר מובנה הוא הגיוני כמטמון חיבורים מקומי בתוך מופע, ושכבה נפרדת נדרשת כשמדובר ביותר משירות אחד וכללי העבודה עם מסד הנתונים צריכים להיות משותפים. ProxySQL בתפקיד הזה מכסה את שני התרחישים — גם שימוש חוזר בחיבורים וגם ריכוז הכללים.
ספקות טכניים: שאלות בנוגע להגדרת המאגר
הספקות לפני הפעלת ProxySQL בדרך כלל אותם ספקות: מה יקרה בעת כשל צומת, האם נדרשים שינויים בקוד, והאם המאגר יעמוד בקפיצה. להלן תשובות קצרות; בניתוח המשימה אנו בודקים כל סעיף על סכימת הרפליקציה שלכם.
מה קורה כשצומת מסד הנתונים מפסיק להגיב?
המאגר בודק זמינות צמתים ומוציא את הצומת שכשל מההפצה, והבקשה עוברת לצומת חי. חיבור שלא הושלם נסגר ולא חוזר למאגר, הלקוח מקבל שגיאה במקום תגובה תלויה; זמן ההמתנה המרבי ומספר הניסיונות מוגדרים במפורש.
האם צריך לשנות קוד באפליקציות?
האפליקציה מתחברת למאגר כמו לשרת רגיל — משתנה רק הכתובת בהגדרות החיבור. שינויים נדרשים במקומות שבהם בקוד מוטמעות כתובות של צמתים מסוימים או לוגיקה עצמאית לבחירת רפליקה: אותה אנו מעבירים לרמת המאגר.
האם המאגר יעמוד בקפיצת עומס?
החיבורים עוברים שימוש חוזר, לכן גידול במספר הלקוחות לא יוצר מפולת חיבורים למסד הנתונים. בקפיצה מופעלים תור בכניסה ומגבלת חיבורים במקביל לצומת: בקשות עודפות ממתינות, ולא מכלות את השרת.
כיצד מתחלקות קריאה וכתיבה?
שאילתות בחירה עוברות לרפליקות, כתיבה וכל מה שבתוך טרנזקציות — לצומת הראשי. שאילתות בחירה עם נעילה מזוהות כמשנות וגם הן עוברות לצומת הראשי, לכן האפליקציה לא מקבלת נתונים מיושנים.
האם אפשר להגביל גישה?
חשבונות והרשאות ניתנים ברמת המאגר, והגישה הישירה לפורטים של מסד הנתונים נסגרת בחומת אש. ביומן רואים מי איזו בקשה שלח — ניתוח האירועים נעשה פשוט יותר באופן ניכר.
נדון במשימה ונחזור עם הערכה ותוכנית
לניתוח ענייני מספיק מה שכבר נמצא בהישג יד: סכימת הסביבה, קונפיגורציות וסטטיסטיקה לתקופה מייצגת. ככל שהנתונים שנשלחו קרובים יותר לתעבורה אמיתית, כך ההערכה והתוכנית מדויקות יותר — בלי ניחושים ובלי "על העין".
מצדכם כדאי לשלוח:
- סכימת הסביבה הנוכחית: אפליקציות, צדדים אחוריים, נקודות כניסה למסד הנתונים ומסלולי תעבורה;
- קונפיגורציות פרוקסי נוכחיות וכללי ניתוב, כולל חלוקת הרשאות והפרדה בין צמתי קריאה לכתיבה;
- ייצוא סטטיסטיקה לתקופה עם עומס מורגש: שיאי חיבורים, שיעור כשלים, זמן המתנה בתור;
- רשימת נקודות גידול ידועות — מה כבר נשבר, היכן העלו מגבלות ידנית;
- אילוצים: חלונות תחזוקה, דרישות שחזור, סדר אישור שינויים.
בסיום הניתוח תקבלו הערכה ותוכנית: סכימת מאגר יעד, סדר עבודה לפי שלבים, קריטריוני קבלה ומערך בדיקות שמראות תוצאה לפני העלאה לסביבת פרודקשן. את המעבר מתכננים בלי עצירת השירות — תחילה מגדירים ProxySQL על עותק של הסביבה, מריצים עומס, ואחר כך מעבירים לפרודקשן.
תארו את המשימה וכתבו את מה שיש — נחזור עם הערכה ותוכנית.







