# פרק 1: ההפלה הראשונה
המזכירה במשרדי חברת NexaTech הביטה בבובי כאילו הוא הגיע מכוכב אחר. הוא לא היה מוזמן דרך כניסה רגילה. מנכ"ל החברה, רונן שפירא, הורה לה לאפשר לו להיכנס ישר למרתף שבו שכנה חוות השרתים. לא שאלות, לא רישום בפנקס המבקרים, לא תג מבקר. רק "תתני לו לעבור".
בובי ירד במדרגות. המעלית הייתה אופציה, אבל הוא התרגל לא להשתמש במעליות בחברות הייטק. פעם הוא נתקע במעלית באמצע עבודה, והמשטרה הגיעה לפני שהוא הספיק לסיים את מה שהתחיל. זה היה לא נעים. אז מדרגות זה בסדר גמור.
חוות השרתים הייתה קטנה. ארבעה ארונות שרתים, מזגן רועש, וריח של פלסטיק מחומם. אור הפלורסנט הרצרץ קצת מדי, מה שהצביע על בעיות חשמל קלות. בובי שם לב לדברים כאלה. לא בגלל שהוא מומחה לחשמל, אלא בגלל שהוא למד לזהות סביבות בעייתיות. חברה שלא מתחזקת את התאורה בחוות השרתים כנראה גם לא מתחזקת את מסד הנתונים כמו שצריך.
רונן חיכה שם, עומד ליד אחד השרתים עם מחשב נייד פתוח. הוא היה גבר בשנות הארבעים, עם חולצה מכופתרת שנראתה כאילו ישן בה. העיגולים השחורים מתחת לעיניים סיפרו את הסיפור. הוא לא ישן הרבה בימים האחרונים.
"בובי טבלאות," רונן אמר. זה לא הייתה שאלה.
"כן."
"תודה שבאת מהר כל כך."
בובי לא ענה. הוא התקרב למחשב הנייד והביט במסך. שורת פקודה פתוחה, עם הודעת שגיאה באדום. מסד הנתונים התרסק באמצע תהליך עדכון גדול, והשאיר את המערכת במצב לא עקבי. טבלאות פגומות, אינדקסים שבורים, קשרים מנותקים. בלגן.
"זה קרה אתמול בלילה," רונן הסביר. הוא דיבר מהר מדי. אנשים תמיד דיברו מהר מדי כשהם לחוצים. "עשינו עדכון גדול למערכת. אמור היה לקחת שעתיים. אחרי ארבע שעות הכל קרס. מאז אנחנו מנסים להבין מה קרה, אבל ככל שאנחנו נוגעים במשהו, זה נעשה יותר גרוע."
בובי התיישב על כיסא המשרדי היחיד בחדר. הכיסא חרק. הוא התחבר למערכת עם הפרטים שרונן נתן לו וקרא את לוג הקבצים. התמונה התבהרה מהר. העדכון ניסה לשנות מבנה של טבלת מפתח, אבל הוא נכשל באמצע. עכשיו המערכת לא מסוגלת להבין איזו גרסה של הטבלה היא הנכונה. יש שתי עותקים חלקיים, שניהם פגומים.
"כמה טבלאות צריך למחוק?" בובי שאל.
רונן פתח מסמך טקסט. "הכנתי רשימה. שלוש טבלאות ראשיות שהתקלקלו. temp_migration_01, temp_migration_02, ו-failed_index_rebuild. אם נמחק אותן ונריץ את העדכון מחדש מנקודת ההתחלה, זה אמור לעבוד."
בובי קרא את השמות. הוא התבונן בתוכן המסד נתונים דרך כלי ניהול שרונן פתח. המערכת הייתה עדיין למחצה חיה. אפשר להריץ שאילתות, אבל כל ניסיון לשנות משהו הוביל לשגיאות.
"יש גיבויים?" בובי שאל.
"כן, אבל הם מלפני שלושה ימים. יש לנו עסקאות חשובות שהתבצעו מאז. לא יכולים להרשות לעצמנו לחזור אחורה."
בובי הבין. זאת הסיבה שהם התקשרו אליו. לא בגלל שהוא הכי טוב, אלא בגלל שהוא הכי מהיר. כשזמן הוא בעיה, אנשים מתקשרים לבובי. הוא מפיל טבלאות מהר יותר מכל אחד אחר. זה לא משהו שהוא מתגאה בו באופן מיוחד, אבל זו העבודה.
"יש עוד מישהו במערכת עכשיו?" בובי שאל.
"לא. סגרנו הכל. אף אחד לא נכנס."
"טוב."
בובי פתח את המסוף. הוא התחיל להקליד. קוד SQL זרם מהאצבעות שלו כמו שפה שניה. הוא לא צריך לחשוב על התחביר. הוא כתב את הפקודות מזיכרון, בודק את התלויות בין הטבלאות, מוודא שאין קשרים נסתרים שעלולים להישבר.
רונן עמד מאחוריו. בובי שמע אותו נושם. נשימות כבדות, לא סדירות. הוא היה לחוץ. זה מובן. החברה שלו תלויה במערכת הזו.
"אתה יכול לשבת," בובי אמר. "זה ולקח כמה דקות."
רונן לא שב. הוא נשאר עומד, צופה במסך. בובי התעלם ממנו והמשיך לעבוד.
הטבלה הראשונה הייתה פשוטה. temp_migration_01 הייתה באמת טבלה זמנית שנוצרה לצורך העדכון. אין לה קשרים חיצוניים, אין מפתחות זרים שמצביעים אליה. בובי הריץ את פקודת ההפלה. DROP TABLE temp_migration_01. המערכת חשבה שתיים שלוש שניות, ואז הטבלה נעלמה.
"אחת נעשתה," בובי אמר.
רונן הנהן. הוא לא אמר כלום.
הטבלה השנייה הייתה מסובכת יותר. temp_migration_02 הייתה גדולה. שלוש גיגה של מידע. הבעיה איתה הייתה שהתהליך הפגום יצר לה אינדקס שלא הסתיים. האינדקס תקוע במצב "בבנייה", ולמערכת אין מושג מה לעשות עם זה. בובי כתב סקריפט קצר שמוחק תחילה את האינדקס, ורק אחר כך את הטבלה עצמה.
זה לקח יותר זמן. המערכת צריכה לעבד את כל המידע, לבדוק שאין נעילות, לוודא שאף תהליך לא מחזיק התייחסות לטבלה. בובי חיכה. הוא הביט בשעון שעל הקיר. חמש דקות עברו מאז שהתחיל.
"זה אמור לקחת כל כך הרבה זמן?" רונן שאל.
"הטבלה גדולה," בובי ענה. "המערכת בודקת הכל. אם תנסה לעצור את זה באמצע, זה רק יחמיר את המצב."
רונן שתק. הוא התחיל לצעוד בחדר. שלושה צעדים קדימה, שלושה צעדים אחורה. קצב קבוע. בובי מצא את זה מעצבן, אבל הוא לא אמר כלום. לקוח לחוץ זה לקוח לחוץ. אי אפשר לעשות הרבה בקשר לזה.
אחרי עוד דקה, הפקודה הסתיימה. הטבלה השנייה נעלמה.
"שתיים," בובי אמר.
רונן הפסיק לצעוד. "נשארה עוד אחת?"
"כן. האחרונה."
failed_index_rebuild הייתה הבעייתית ביותר. בובי התבונן במבנה שלה וראה משהו שלא ציפה לו. הטבלה הזו הייתה לא רק טבלה זמנית. היא נוצרה כחלק מתהליך שניסה לבנות מחדש אינדקס על טבלה אחרת, טבלה שנראתה כמו טבלת לקוחות.
זה קצת מוזר. למה תהליך עדכון ינסה לבנות מחדש אינדקס על טבלת לקוחות? בובי בדק את הסקריפט של העדכון. הוא לא הבין את כל הקוד, אבל נראה שמישהו הוסיף שלב שלא תואם למסמך שרונן הראה לו.
"מי כתב את סקריפט העדכון?" בובי שאל.
"המפתח הראשי שלנו. למה?"
"רק שאלה."
בובי החליט לא להיכנס לזה. זו לא באמת עניין שלו. הוא כאן כדי למחוק טבלאות, לא כדי לחקור למה העדכון נכשל. הוא הריץ את הפקודה למחיקת failed_index_rebuild.
המערכת הגיבה מיידית. הטבלה נמחקה תוך שניות.
"זהו," בובי אמר. "שלוש הטבלאות נמחקו."
רונן נשף אויר. "תודה. תודה רבה. אני לא יודע מה היינו עושים בלעדיך."
בובי התנתק מהמערכת. הוא לא אהב להישאר מחובר לאחר שהעבודה נגמרת. זה השאיר עקבות. לא שהוא עושה משהו לא חוקי, אבל פשוט הרגל טוב לשמור על דברים נקיים.
"אני אשלח לך את החשבונית מחר," בובי אמר.
"בטח, בטח. אין בעיה."
רונן ניגש למחשב הנייד. הוא התחיל להקליד, כנראה בודק שהמערכת אכן חזרה למצב יציב יותר. בובי קם מהכיסא. העבודה הסתיימה. הוא חשב על הדרך הביתה. אולי יעצור לקנות משהו לאכול.
"רגע," רונן אמר. הקול שלו השתנה. "יש כאן בעיה."
בובי עצר ליד המדרגות. "מה הבעיה?"
"הטבלה. customers_main. היא לא כאן."
בובי חזר אל המחשב. הוא התבונן במסך. רונן הריץ שאילתה שמציגה את רשימת הטבלאות במסד הנתונים. customers_main באמת לא הייתה שם.
"זה מוזר," בובי אמר. הוא חשב לרגע. "אולי היא נמחקה כחלק מהקריסה המקורית?"
"לא." רונן הניד בראשו. "בדקתי את זה לפני שהתקשרתי אליך. הטבלה הייתה שם. יש לי צילום מסך מהבוקר."
הוא פתח תיקייה במחשב והראה לבובי את צילום המסך. אכן, customers_main הייתה ברשימה הבוקר.
בובי התחבר שוב למערכת. הוא בדק את היסטוריית הפקודות. הוא ראה את שלוש הפקודות שהוא הריץ. DROP TABLE temp_migration_01. DROP TABLE temp_migration_02. DROP TABLE failed_index_rebuild. שום דבר על customers_main.
"אולי התהליך שלך מחק אותה בטעות?" רונן שאל. הקול שלו נשמע מפוקפק.
"אני מחקתי רק את מה שביקשת," בובי אמר. "שלוש טבלאות."
הוא בדק את לוג המערכת. היסטוריה מלאה של כל מה שקרה במסד הנתונים. הוא גלל אחורה, מחפש את הרגע שבו customers_main נמחקה.
ואז הוא ראה את זה.
לא הייתה פקודת DROP TABLE ישירה. במקום זה, הייתה שרשרת של אירועים. כש-failed_index_rebuild נמחקה, זה הפעיל טריגר. הטריגר היה שארית מהעדכון הכושל. הוא אמור היה לנקות קבצים זמניים, אבל מישהו כתב אותו בצורה שגויה. במקום למחוק קבצים זמניים, הוא מחק את הטבלה שהאינדקס התייחס אליה. customers_main.
זה היה מורכב. הטריגר לא היה אמור להישאר שם. הוא היה אמור להימחק אוטומטית אם העדכון היה מסתיים בהצלחה. אבל בגלל שהעדכון נכשל, הטריגר נשאר. וכשבובי מחק את failed_index_rebuild, הטריגר הופעל.
בובי הסביר את זה לרונן. הוא הראה לו את לוג המערכת, את הטריגר השגוי, את השרשרת של אירועים.
רונן הביט במסך. הפנים שלו היו חיוורות. "אז טבלת הלקוחות שלנו נעלמה לחלוטין?"
"כן."
"וזה בגלל הטריגר הזה?"
"כן."
"אבל אתה הפעלת אותו."
בובי לא אהב את הכיוון שזה לקח. "הפעלתי את מה שביקשת. מחקתי את השלוש טבלאות. הטריגר היה בעיה בקוד שלכם."
רונן התיישב על הכיסא. הוא נראה כאילו מישהו היכה אותו. "אבל הלקוחות. כל הנתונים. רשימת התפוצה, ההיסטוריה, הכל."
"יש לכם גיבוי," בובי אמר. "אמרת שיש גיבוי מלפני שלושה ימים."
"כן, אבל שלושה ימים זה הרבה. יש לנו מאות עסקאות שהתבצעו מאז. לקוחות חדשים שנרשמו. עדכונים."
"זה מצטער," בובי אמר. "אבל זו לא באמת אשמתי."
רונן הרים את הראש. "לא אשמתך? מחקת את הטבלה."
"הטריגר מחק את הטבלה. אני מחקתי את failed_index_rebuild, שזה מה שביקשת."
"לא ביקשתי שתמחק את customers_main."
"לא מחקתי אותה ישירות. זה קרה בגלל באג בקוד שלכם."
הם הביטו זה בזה. בובי ידע לאן זה הולך. הוא ראה את זה קורה לפני. כשמשהו משתבש, אנשים מחפשים על מי להאשים. זה לא משנה מי באמת אחראי. מה שחשוב זה מי נמצא שם כשזה קרה.
"אני צריך להתקשר למנהל הטכני," רונן אמר. הוא הוציא את הטלפון. "הוא צריך לדעת על זה."
בובי ידע שזה הזמן לעזוב. הוא לא יכול לעשות יותר כאן. הטבלה נמחקה. זה עובדה. אם הם רוצים להחזיר אותה, הם צריכים להשתמש בגיבוי. זה לא מושלם, אבל זו האופציה היחידה.
"אני הולך," בובי אמר.
רונן לא התייחס אליו. הוא כבר דיבר בטלפון, מסביר למישהו מה קרה. בובי שמע אותו אומר "בובי טבלאות" ואז "customers_main נמחקה". הוא לא שמע את השאר.
הוא עלה במדרגות. המזכירה עדיין ישבה בקבלה, אבל היא לא הביטה בו כשהוא עבר. אולי היא קיבלה הוראה לא לעשות קשר עין. אנשים מוזרים לגבי בובי. הם יודעים מי הוא, הם יודעים מה הוא עושה, אבל הם מעדיפים לא לדבר איתו יותר מדי.
בחוץ, האוויר היה קר. השמש כבר התחילה לשקוע. בובי הביט בשעון. חמש אחרי שש. העבודה לקחה פחות משעה. מהיר, כמו תמיד.
הוא חשב על מה שקרה. הטריגר היה בעיה אמיתית. מישהו כתב אותו בצורה שגויה, ואף אחד לא תפס את זה לפני שהיה מאוחר מדי. זה לא טעות שלו. הוא עשה בדיוק מה שביקשו ממנו. אבל זה לא משנה. בסוף, customers_main נמחקה בזמן שהוא היה מחובר למערכת. זה מספיק כדי שאנשים יזכרו.
בובי טבלאות. מפיל טבלאות. גם כאלו שלא אמור למחוק.
הוא התחיל ללכת לכיוון החניון. המכונית שלו חיכתה שם. טויוטה ישנה שהוא קנה במזומן לפני כמה שנים. אמינה, לא מושכת תשומת לב. בדיוק מה שהוא צריך.
הטלפון שלו צלצל. הוא הוציא אותו והביט במסך. מספר לא מוכר. הוא לא ענה. לעולם לא עונה למספרים לא מוכרים מיד אחרי עבודה. זה יכול להיות הלקוח, זועם, רוצה להאשים אותו ביותר דברים. או שזה יכול להיות מישהו אחר שמחפש את השירותים שלו. בכל מקרה, זה יכול לחכות.
הוא הגיע למכונית ונכנס פנימה. המנוע התעורר לחיים אחרי פנייה שנייה של המפתח. בובי חיבר את חגורת הבטיחות ויצא מהחניון.
בדרך הביתה, הוא חשב על הטריגר. זה היה באמת באג מעניין. מי שכתב את הסקריפט של העדכון בטח לא בדק אותו מספיק טוב. או אולי הוא בדק, אבל במערכת שונה, שבה הטריגר לא נשאר אחרי כישלון. כך או כך, זה נכשל. ובובי היה שם כשזה קרה.
זה לא הפעם הראשונה. פעם, לפני שנתיים, הוא נקרא לחברת סטארטאפ שהמערכת שלה קרסה. הם ביקשו ממנו למחוק טבלת לוגים ישנה שתפסה יותר מדי מקום. הוא מחק אותה, והמערכת התאוששה. אבל אחרי שבוע התברר שהטבלה הזו הכילה גם מידע חשוב על עסקאות שנכשלו, מידע שהיה אמור לעבור למחלקת הנהלת החשבונות. אף אחד לא אמר לו את זה. הם רק אמרו "טבלת לוגים ישנה". אבל בסוף, הם האשימו אותו. "בובי מחק את המידע שלנו."
זה המוניטין. בובי מפיל טבלאות. מהר, יעיל, ובלי שאלות. אבל אם משהו משתבש, אם משהו נמחק שלא היה צריך להימחק, זה תמיד חוזר אליו. הוא זה שלחץ על הכפתור. הוא זה שהריץ את הפקודה.
אנשים אוהבים להאשים. זה יותר קל מלקחת אחריות.
בובי הגיע הביתה. דירה קטנה בקומה השנייה של בניין ישן. שכונה שקטה, שכנים שלא מתעניינים במה הוא עושה. הוא נכנס פנימה, השליך את המפתחות על השולחן, ופתח את המקרר. בירה אחת נשארה. הוא לקח אותה והתיישב על הספה.
הטלוויזיה הייתה כבויה. הוא לא הדליק אותה. הוא רק ישב שם, שותה מהבירה, חושב על customers_main. שלוש גיגה של נתונים. אלפי לקוחות. היסטוריה שנבנתה במשך שנים. כולה נעלמה בגלל טריגר שלא היה אמור להיות שם.
זה לא היה הפעם הראשונה, והוא ידע שזה לא תהיה האחרונה. כל עוד אנשים כותבים קוד עם באגים, כל עוד מערכות קורסות ומסדי נתונים מתקלקלים, תמיד יהיה צורך במישהו כמו בובי. מישהו שמוכן לבוא, למחוק את מה שצריך למחוק, ולעזוב.
הטלפון צלצל שוב. אותו מספר לא מוכר. הפעם הוא ענה.
"כן?"
"בובי טבלאות?" קול של אישה, צעירה.
"כן."
"שמעתי עליך. יש לי בעיה עם מסד נתונים. אפשר לדבר?"
בובי התבונן בבירה בידו. היא כמעט ריקה.
"שלחי לי את הפרטים במייל," הוא אמר. "אני אחזור אליך מחר."
"זה דחוף."
"הכל דחוף. מייל, ואני אחזור."
הוא ניתק. שתה את שארית הבירה. קם מהספה והלך למטבח. בארון היה שקית פסטה. בצמר היו עגבניות. הוא החליט לבשל משהו פשוט.
תוך כדי שהמים התחממו על הכיריים, הוא חשב על רונן ועל הפנים החיוורות שלו כשהבין שcustomers_main נעלמה. זו תמיד אותה תגובה. זעזוע, הכחשה, ואז כעס. תמיד כעס. צריך מישהו לאשום.
בובי שפך את הפסטה למים הרותחים. הוא ידע שהחשבונית שלו לא תשולם. רונן ימצא תירוץ. "אתה גרמת נזק," הוא יגיד. "אתה צריך לפצות אותנו." ואז יהיו אולי איומים משפטיים, או סתם התעלמות. בכל מקרה, הכסף לא יגיע.
זה חלק מהעבודה. לא תמיד מקבלים מה שמגיע. לפעמים העבודה מסתיימת עם טבלאות נעלמות ולקוחות זועמים. ובסוף, מה שנשאר זה המוניטין. בובי טבלאות. מסוכן מאוד.
הוא אכל את הפסטה לאט. לא חשב על כלום מיוחד. עוד יום, עוד עבודה. מחר יגיע המייל מהאישה עם הבעיה הדחופה. הוא יקרא, יבין מה היא צריכה, ויחליט אם לקחת את העבודה או לא.
אחרי האוכל, הוא התקלח והלך לישון. המיטה הייתה קשה, אבל הוא התרגל אליה. הוא שכב במשך כמה דקות, מביט בתקרה, חושב על customers_main שוב.
ואז הוא נרדם. לא היו חלומות. רק שינה שחורה ושקטה עד הבוקר.
Comments (0)
No comments yet. Be the first to share your thoughts!