# פרק 2: רשות המסים בובי התעורר לצלצול הטלפון. הוא פתח עין אחת והביט בשעון על השידה. שש וחצי בבוקר. מוקדם מדי. הוא סגר את העין וניסה להתעלם, אבל הטלפון לא הפסיק. הצלצול חזר על עצמו שוב ושוב, עד שהוא נאלץ למתוח יד ולהוציא את המכשיר מהשקע בקיר. המסך הראה חמש שיחות שלא נענו. כולן מאותו מספר. המספר הלא מוכר מאתמול. האישה עם הבעיה הדחופה. הוא ישב על המיטה וחיכה שהטלפון יפסיק לצלצל. כשזה קרה, היה שקט לכמה שניות. אז זה התחיל שוב. בובי לחץ על כפתור הקבלה. "כן?" הקול שלו נשמע מחוספס. הוא לא שתה מספיק מים אתמול. "בובי טבלאות?" אותו קול צעיר, אבל הפעם יותר דחוף. "אני התקשרתי חמש פעמים." "ראיתי." "צריך אותך עכשיו. ממש עכשיו." בובי קם מהמיטה והלך למטבח. הוא פתח את הברז ושתה מים ישר מהזרם. המים היו קרים. "אמרתי לך אתמול לשלוח מייל." "לא היה זמן." היא נשמעה כאילו היא רצה. בובי שמע רעש של מכוניות ברקע. "זה רשות המסים. המסד נתונים המרכזי קרס לפני שלוש שעות." בובי הפסיק לשתות. רשות המסים. זה לא משהו קטן. זה ממשלה. "מה קרה?" הוא שאל. "לא יודעת בדיוק. שרת ראשי נפל, והגיבוי לא עלה אוטומטית כמו שהוא אמור." היא המשיכה לדבר מהר. "יש לנו מערכת גיבוי משנית שתיכנס לפעולה בעוד שעתיים. אבל יש בעיה. אם לא נמחק טבלאות מסוימות עכשיו, המערכת תכתוב נתונים כפולים שיהרסו את כל הגיבוי." "למה את לא מוחקת את הטבלאות בעצמך?" "זה מסובך. יש תלויות, אני לא בטוחה איך לעשות את זה נכון. שמעתי עליך מחבר. אמרו שאת מהיר." "מי אמר?" בובי רצה לדעת. אולי מישהו מהעבודות הקודמות. "לא משנה. אתה יכול לבוא?" בובי הביט בשעון על הקיר. שש וארבעים. הדרך לרשות המסים לוקחת בערך עשרים דקות במכונית. הוא יכול להגיע לפני שבע וחצי אם הוא יוצא עכשיו. "כמה אתם משלמים?" הוא שאל. היא היססה. "אנחנו ממשלה. יש תעריפים קבועים." "כמה?" "אלפיים שקל לשעה." זה היה פחות ממה שבובי בדרך כלל לוקח, אבל רשות המסים זה לא ארגון שאפשר להתמקח איתו. הם משלמים מה שהם משלמים, ולפחות הם משלמים. לא כמו סטארטאפים שמבטיחים תשלום ואז נעלמים. "בסדר," הוא אמר. "אני מגיע." "תודה. תודה רבה. אני שולחת לך את הכתובת עכשיו." היא ניתקה. בובי הביט במכשיר. הודעה הגיעה תוך שניות. כתובת במרכז העיר, בניין ממשלתי גדול שהוא הכיר. הוא היה שם פעם אחת, לפני כמה שנים, בסיפור לא קשור. הוא התקלח מהר, לבש בגדים נקיים, ויצא מהדירה. הבניין היה שקט. השכנים עדיין ישנו. בובי ירד במדרגות והגיע לחניון. המכונית חיכתה שם, אותה טויוטה ישנה. הוא נכנס והתניע את המנוע. הדרך הייתה ריקה יחסית. עדיין מוקדם מדי לשעת עומס. בובי נסע בשקט, חושב על מה שהאישה אמרה. טבלאות שצריך למחוק כדי למנוע כתיבה כפולה של נתונים. זה נשמע הגיוני. כשמערכת גיבוי עולה, היא צריכה לדעת איפה להתחיל. אם יש טבלאות זמניות או פגומות, זה יכול לבלבל אותה. אבל משהו בזה לא הרגיש נכון. למה לא פשוט לכבות את המערכת הראשית ולתת לגיבוי לעלות לבד? למה צריך למחוק משהו? הוא הגיע לבניין רשות המסים. מבנה גדול, אפור, עם הרבה חלונות. חניון תת קרקעי שדרש כרטיס כניסה. בובי חנה במקום של מבקרים והוציא את הטלפון. הוא חייג למספר שהאישה התקשרה ממנו. היא ענתה מיד. "אתה כאן?" "בחניון." "אני יורדת." בובי חיכה ליד המכונית. הוא הביט סביב. החניון היה כמעט ריק. כמה מכוניות פזורות פה ושם, אבל רובו ריק. זה הגיוני. עדיין מוקדם. אחרי כמה דקות, דלת נפתחה והאישה יצאה. היא הייתה צעירה, אולי עשרים ושמונה או שלושים. שיער קצר וכהה, משקפיים, בגדים פורמליים. היא נראתה לחוצה. "בובי?" היא שאלה. "כן." "אני מיכל. מנהלת מערכות מידע פה." היא הושיטה יד. בובי לחץ עליה. היד הייתה קרה. "בואי נתחיל," הוא אמר. היא הנהנה והובילה אותו לתוך הבניין. מעלית לקומה השביעית, ואז מסדרון ארוך עם דלתות משני הצדדים. הם הגיעו לחדר גדול מלא בשולחנות ומחשבים. היו שם כמה אנשים, כולם נראו מתוחים. הם הביטו בבובי כשהוא נכנס, אבל אף אחד לא אמר כלום. מיכל הובילה אותו לפינה של החדר, שם עמד שולחן גדול עם שלושה מסכים. "זה התחנה הראשית," היא אמרה. "מכאן אפשר לגשת למסד הנתונים." בובי התיישב. הוא הביט במסכים. אחד הראה צריכת משאבים של השרתים, השני הראה לוג של שגיאות, והשלישי היה פתוח לממשק ניהול מסד נתונים. "אז מה בדיוק קרה?" הוא שאל. מיכל משכה כיסא אחר והתיישבה לידו. "השרת הראשי קרס בגלל בעיית חומרה. דיסק קשיח נשרף או משהו כזה. הגיבוי האוטומטי אמור היה לעלות, אבל הוא לא. מתברר שהיה באג בסקריפט שמפעיל אותו." "ואיפה הגיבוי עכשיו?" "מנסים לתקן את הסקריפט. זה ייקח עוד שעה, שעה וחצי אולי." "אז למה צריך למחוק משהו?" מיכל הצביעה על המסך. "יש לנו תהליך שרץ כל הזמן. הוא אוסף נתונים מהמשתמשים ושומר אותם בטבלאות זמניות. כשהשרת הראשי קרס, התהליך המשיך לרוץ על שרת משני, ולכתוב לטבלאות אלו. אם הגיבוי יעלה והתהליך יראה שהטבלאות האלו כבר קיימות, הוא יתבלבל וייצור כפילויות." בובי הבין. זה באמת יכול להיות בעיה. מידע כפול במסד נתונים של רשות המסים זה אסון. אנשים יקבלו דרישות תשלום כפולות, או שהמערכת תחשב שמישהו חייב פעמיים יותר ממה שהוא באמת חייב. "איזה טבלאות צריך למחוק?" הוא שאל. מיכל פתחה קובץ טקסט על אחד המסכים. "הכנתי רשימה. חמש טבלאות. temp_user_data_01 עד temp_user_data_05. אלו הטבלאות שהתהליך כותב אליהן." בובי קרא את הרשימה. השמות היו די סטנדרטיים. הוא פתח את ממשק ניהול מסד הנתונים והתחבר עם הפרטים שמיכל נתנה לו. המערכת הייתה ענקית. מאות טבלאות, אלפי שורות של מידע. הוא חיפש את הטבלאות מהרשימה. temp_user_data_01 הייתה שם. הוא בדק את המבנה שלה. שדות פשוטים. מזהה משתמש, תאריך, כמה ערכים נומריים. נראה תמים. "אפשר למחוק אותן?" מיכל שאלה. בובי לא ענה מיד. הוא המשיך לבדוק. הוא רצה לראות תחילה איך הטבלאות האלו מתחברות לשאר המערכת. יש להן קשרים חיצוניים? מפתחות זרים? טריגרים? הוא בדק את הקשרים. לא היו מפתחות זרים. זה אומר שאין קשרים ישירים לטבלאות אחרות. זה טוב. אבל היו טריגרים. הוא מצא שלושה טריגרים שקשורים לטבלאות האלו. "יש פה טריגרים," הוא אמר. "כן, אני יודעת." מיכל הנהנה. "הם אמורים לעדכן טבלת סיכום כללית כשנתונים נכתבים לטבלאות הזמניות. אבל זה לא רלוונטי כרגע. אנחנו לא צריכים את זה." בובי לא אהב טריגרים. הוא ראה יותר מדי פעמים מה קורה כשטריגר מתנהג לא כמו שצריך. אתמול, ב-NexaTech, זה היה בדיוק הבעיה. טריגר שלא היה צריך להיות שם מחק טבלה שלמה. "מה הטריגרים האלו עושים בדיוק?" הוא שאל. מיכל התבוננה במסך. "הם מעדכנים טבלה שנקראת summary_tax_data. זו טבלה שמכילה סיכומים של נתונים ממשתמשים. כל פעם שמישהו מזין מידע חדש, הטריגר מעדכן את הסיכום." בובי חיפש את summary_tax_data במסד הנתונים. היא הייתה שם. טבלה גדולה, עם מיליוני שורות. הוא בדק את המבנה. זה היה טבלה חשובה. לא משהו שרוצים לאבד. "אם אני אמחק את הטבלאות הזמניות, הטריגרים יופעלו?" הוא שאל. "לא." מיכל הייתה בטוחה. "הטריגרים מופעלים רק כשכותבים לטבלאות או מעדכנים אותן. מחיקה לא אמורה להפעיל אותם." בובי לא היה בטוח. הוא ראה טריגרים שמופעלים גם במחיקה. זה תלוי איך הם מוגדרים. הוא בדק את הקוד של הטריגרים. אחד מהם אכן היה מוגדר להפעלה גם במחיקה. ON DELETE. "הטריגר השלישי," הוא אמר. "הוא מופעל במחיקה." מיכל התקרבה למסך. היא קראה את הקוד. "אה, נכון. זה טריגר שאמור לנקות את summary_tax_data כשמוחקים נתונים זמניים. זה בסדר, זה לא יגרום בעיה." "אתם בטוחה?" "כן. זה פשוט מוחק שורות שמתאימות למזהה של הנתונים הזמניים. לא משהו מסוכן." בובי לא אהב את זה, אבל הוא גם לא היה מומחה למערכת הספציפית הזו. אולי היא צודקת. הוא החליט להמשיך בזהירות. "אני אתחיל עם הטבלה הראשונה," הוא אמר. "אם הכל בסדר, נמשיך לשאר." "בסדר. אבל תזדרז. יש לנו פחות משעתיים." בובי התכונן להריץ את הפקודה למחיקת temp_user_data_01. הוא כתב את הקוד ובדק אותו פעמיים. DROP TABLE temp_user_data_01. הכל נראה בסדר. אז הוא שם לב למשהו. היה עוד אדם שמחובר למערכת. הוא ראה את זה בפינה של אחד המסכים. חיבור פעיל נוסף. "מי עוד מחובר למערכת?" הוא שאל. מיכל הביטה במסך. "זה אני. יש לי חיבור מהמחשב הנייד שלי." "למה?" "אני עוקבת אחרי מה שקורה. זה חלק מהעבודה שלי." בובי לא התנגד, אבל הוא העדיף לעבוד לבד. כשיש יותר מדי אנשים מחוברים, זה יכול לגרום לבעיות. נעילות, התנגשויות, כל מיני דברים לא נעימים. "אפשר שתתנתקי לרגע?" הוא שאל. "רק בזמן שאני עובד." מיכל היססה. "אני צריכה לעקוב אחרי מה שקורה." "את יכולה לעקוב מהמסך הזה. אני אראה לך את הלוג." היא הסכימה בחוסר רצון. היא התנתקה מהמחשב הנייד. בובי חיכה עד שהוא ראה שהחיבור שלה נסגר. עכשיו הוא היה היחיד במערכת. הוא הריץ את הפקודה למחיקת temp_user_data_01. המערכת חשבה כמה שניות, ואז הטבלה נעלמה. הטריגר לא הופעל. הכל היה שקט. "אחת נעשתה," הוא אמר. מיכל נראתה מרוצה. "מעולה. תמשיך." בובי עבר לטבלה השנייה. temp_user_data_02. אותו תהליך. בדיקה של המבנה, בדיקה של קשרים, בדיקה של טריגרים. הכל נראה זהה לטבלה הראשונה. הוא הריץ את הפקודה. הטבלה נמחקה. שוב, אין בעיות. "שתיים," הוא אמר. הוא המשיך לטבלה השלישית. temp_user_data_03. אבל כשהוא בדק את המבנה, הוא שם לב למשהו מוזר. הטבלה הזו הייתה שונה במעט מהשתיים הראשונות. היה לה שדה נוסף. שדה שנקרא link_to_summary. "מה השדה הזה?" הוא שאל, מצביע על המסך. מיכל התבוננה. "אה, זה קישור לטבלת הסיכום. זה שומר את המזהה של השורה ב-summary_tax_data שמתאימה לנתונים הזמניים." "למה צריך את זה?" "זה עוזר לטריגר לדעת איזה שורה לעדכן. במקום לחפש את כל הטבלה, הוא פשוט הולך ישר לשורה הנכונה." בובי חשב על זה. זה נשמע הגיוני, אבל זה גם מסוכן. אם הטריגר משתמש בשדה הזה, זה אומר שיש קשר ישיר בין הטבלה הזמנית לבין summary_tax_data. מחיקת הטבלה הזמנית עלולה להשפיע על טבלת הסיכום. "אני רוצה לבדוק את הטריגר עוד פעם," הוא אמר. הוא פתח את הקוד של הטריגר ששייך ל-temp_user_data_03. זה היה מורכב יותר מהטריגרים של השתיים הראשונות. הטריגר לא רק מעדכן את summary_tax_data. הוא גם בודק אם יש שורות ב-summary_tax_data שלא מתאימות יותר לשום דבר, ומוחק אותן. זה בעייתי. אם הטריגר מוחק שורות מ-summary_tax_data, זה אומר שמידע יכול לאבד. מידע שאולי לא קשור לטבלה הזמנית בכלל. "הטריגר הזה מוחק שורות מ-summary_tax_data," בובי אמר. "כן, אבל רק שורות שכבר לא רלוונטיות. זה בסדר." "איך הוא יודע איזה שורות לא רלוונטיות?" מיכל הסבירה. "הוא בודק את השדה link_to_summary. אם אין שום טבלה זמנית שמצביעה על שורה מסוימת, זה אומר שהשורה הזו לא נחוצה יותר." בובי לא אהב את זה. זה נשמע כמו לוגיקה מסובכת מדי. מה אם יש שורות ב-summary_tax_data שלא קשורות לטבלאות הזמניות? מה אם הן שם מסיבות אחרות? "אני לא בטוח שזה בטוח," הוא אמר. מיכל נראתה מתוחה. "מה הבעיה?" "הטריגר יכול למחוק שורות שלא קשורות לטבלה הזמנית. זה עלול להרוס נתונים חשובים." "לא." מיכל הנהנה בחוזקה. "הטריגר בודק בדיוק מה צריך למחוק. זה נבדק כבר מאות פעמים." בובי הביט בה. היא הייתה בטוחה, אבל הוא ראה הרבה אנשים בטוחים בעצמם שטעו. אתמול, רונן היה בטוח שהעדכון יעבוד. והוא לא עבד. "אני רוצה לבדוק את summary_tax_data לפני שאני ממשיך," הוא אמר. "אין לנו זמן לזה." מיכל הצביעה על השעון. "נשארו לנו שעה וחמש עשרה דקות. אם לא תסיים עד אז, הגיבוי יעלה והכל יתבלבל." בובי ידע שהיא צודקת לגבי הזמן, אבל הוא גם ידע שאם הוא ימחק משהו שלא צריך, זה יהיה יותר גרוע. הוא הביט במסך, בטבלת summary_tax_data. מיליוני שורות. אין לו מספיק זמן לבדוק את כולן. "אני יכול לבדוק דגימה קטנה," הוא אמר. "רק כדי לראות שהטריגר באמת עובד כמו שצריך." מיכל נאנחה. "בסדר. אבל תעשה את זה מהר." בובי כתב שאילתה שמוצאת את עשר השורות הראשונות ב-summary_tax_data שיש להן link_to_summary שמצביע על temp_user_data_03. הוא הריץ את השאילתה. המערכת החזירה עשר שורות. הוא בדק אותן. נראה שהן קשורות לנתונים שהוזנו היום, בזמן שהשרת הראשי היה למטה. "נראה בסדר," הוא אמר. הוא היה מוכן למחוק את temp_user_data_03 כשמשהו תפס את העין שלו. בפינה של המסך, בלוג המערכת, הייתה הודעת אזהרה. WARNING: Duplicate key in summary_tax_data. מפתח כפול. זה לא אמור להיות. summary_tax_data אמורה להיות טבלה עם מפתח ייחודי לכל שורה. אם יש כפילויות, זה אומר שהמערכת כבר מבולבלת. "יש פה בעיה," הוא אמר. הוא הראה למיכל את ההודעה. היא הביטה במסך. "זה בטח משהו זמני. זה יתוקן כשהגיבוי יעלה." "או שזה יחמיר." בובי לא היה משוכנע. "אם יש כבר כפילויות, מחיקת הטבלאות הזמניות עלולה ליצור עוד כפילויות." מיכל הביטה בשעון. "אין לנו זמן להיכנס לזה. אנחנו צריכים למחוק את הטבלאות עכשיו." בובי הרגיש לחץ. הוא ידע שהיא לחוצה, והוא הבין למה. אבל הוא גם ידע שאם הוא יעשה משהו לא נכון, זה יכול להיות גרוע יותר מאשר פשוט לחכות שהגיבוי יעלה. "אני חושב שאנחנו צריכים לחכות," הוא אמר. "לתת לגיבוי לעלות, ואז לנקות את הבלגן." "לא." מיכל הנהנה בחוזקה. "אם לא נמחק עכשיו, הגיבוי ייכנס למצב בלתי עקבי. זה יכול לקחת ימים לתקן. אנחנו צריכים למחוק עכשיו." בובי הביט בה. היא הייתה נחושה. הוא יכול היה לראות את זה בעיניים שלה. היא לא הולכת לשנות דעה. "בסדר," הוא אמר. "אני אמחק את temp_user_data_03. אבל אם משהו ישתבש, זה על האחריות שלך." "מובן." מיכל הנהנה. "אני לוקחת אחריות מלאה." בובי כתב את הפקודה למחיקת temp_user_data_03. הוא בדק אותה שלוש פעמים לפני שהוא הריץ. DROP TABLE temp_user_data_03. המערכת חשבה. זה לקח יותר זמן הפעם. הטבלה הייתה יותר גדולה, והטריגר היה מורכב יותר. בובי הביט בלוג המערכת. הטריגר התחיל לעבוד. הוא בדק את summary_tax_data, מצא שורות שלא קשורות יותר לשום דבר, ומחק אותן. אחרי דקה, הטבלה נמחקה. הטריגר סיים לעבוד. בובי בדק את summary_tax_data. היו עכשיו פחות שורות. הטריגר מחק חלק מהן. "זה נראה בסדר," מיכל אמרה. "תמשיך." בובי עבר לטבלה הרביעית. temp_user_data_04. הוא בדק את המבנה שלה. היא הייתה זהה ל-temp_user_data_03. אותם שדות, אותם טריגרים. הוא התכונן למחוק אותה, אבל משהו עצר אותו. הוא התבונן ב-summary_tax_data שוב. משהו שם לא היה נכון. היו שורות שנראו תמוהות. ערכים נומריים שלא הגיוניים. "יש פה שורות עם ערכים שליליים," הוא אמר. מיכל הביטה. "איפה?" הוא הצביע על המסך. כמה שורות ב-summary_tax_data הכילו מספרים שליליים בשדות שאמורים להיות תמיד חיוביים. סכומי מס, הכנסות, דברים כאלו. "זה לא אמור להיות," מיכל אמרה. היא נראתה מודאגת. "אולי זה בגלל הטריגר." "או בגלל משהו אחר." בובי לא היה בטוח. "אולי הבעיה הייתה שם עוד לפני שהתחלתי." מיכל פתחה את המחשב הנייד שלה ובדקה משהו. "יש לי צילום מסך של summary_tax_data מהבוקר. רגע, אני בודקת." היא גללה דרך קובץ תמונה. אחרי רגע היא אמרה, "הערכים השליליים לא היו שם הבוקר. זה משהו שקרה עכשיו." בובי חשב. אם הערכים השליליים לא היו שם לפני, זה אומר שהטריגר שהוא הפעיל יצר אותם. אבל איך? הטריגר אמור רק למחוק שורות, לא לשנות ערכים. הוא בדק שוב את הקוד של הטריגר. והפעם הוא ראה משהו שהחמיץ קודם. הטריגר לא רק מוחק שורות. הוא גם מעדכן שורות אחרות, תלוי בתנאים מסוימים. הלוגיקה הייתה מורכבת ולא ממש ברורה. "הטריגר משנה ערכים," הוא אמר. "לא רק מוחק." מיכל קראה את הקוד איתו. "נכון. זה אמור לתקן סכומים כפולים. אם יש שתי שורות שמצביעות על אותו משתמש, הטריגר מאחד אותן לשורה אחת." "וזה יוצר ערכים שליליים?" "לא אמור." מיכל נראתה מבולבלת. "זה אמור לחבר את הערכים, לא להפחית." בובי הביט בקוד שוב. ואז הוא ראה את הבאג. הטריגר אמור היה לחבר ערכים, אבל מישהו כתב את הנוסחה בצורה שגויה. במקום + הוא כתב -. זו טעות פשוטה, אבל היא יוצרת נזק משמעותי. "הנה הבעיה," הוא אמר. הוא הצביע על השורה בקוד. מיכל הביטה. היא הרכינה את ראשה והתבוננה מקרוב. "זה באג," היא אמרה בשקט. "איך לא תפסנו את זה קודם?" "כי אף אחד לא בדק את הקוד בזהירות מספקת." בובי נאנח. "זה קורה הרבה." מיכל התיישבה בחזרה על הכיסא. "אז מה עכשיו? אם נמשיך למחוק, זה רק יחמיר את המצב." "נכון." בובי הסכים. "צריך לתקן את הטריגר לפני שממשיכים." "אין לנו זמן." מיכל הביטה בשעון. "נשארו לנו פחות משעה." בובי חשב. הוא יכול לנסות לתקן את הטריגר, אבל זה יכול לקחת זמן. ואם הוא יעשה טעות, זה עלול להיות גרוע יותר. החלופה היא פשוט לא לעשות כלום, לתת לגיבוי לעלות, ולהתמודד עם הבעיה אחר כך. "אני חושב שאנחנו צריכים להפסיק," הוא אמר. "לא למחוק יותר כלום." מיכל הביטה בו. "אבל הגיבוי. הוא ייצור כפילויות." "יצור. ואז אתם תנקו אותן. זה יקח זמן, אבל זה יותר בטוח מאשר להמשיך עם טריגר שבור." מיכל לא נראתה משוכנעת. "המנהלת הטכנית שלי לא תסכים. היא אמרה למחוק את כל חמש הטבלאות." "המנהלת הטכנית שלך לא יודעת שיש באג בטריגר." "אז נגיד לה." בובי הנהן. "בסדר. קראי לה. תראי לה מה מצאנו." מיכל הוציאה את הטלפון והתקשרה. היא דיברה בקול נמוך, מסבירה את המצב. בובי שמע רק חצי מהשיחה, אבל הוא הבין שהמנהלת לא מרוצה. אחרי כמה דקות, מיכל ניתקה. "היא בדרך. היא רוצה לדבר איתך." בובי חיכה. הוא הביט במסך, בקוד השגוי של הטריגר. זו הייתה טעות כל כך פשוטה. סימן פלוס במקום סימן מינוס. אבל זה יכול להרוס את כל המערכת. אחרי כמה דקות, אישה נכנסה לחדר. היא הייתה בשנות החמישים, שיער אפור קצר, בגדים פורמליים. היא נראתה רצינית ומעט כועסת. "אני דנה, מנהלת טכנית," היא אמרה. "מי אתה?" "בובי טבלאות." דנה הביטה בו. משהו בעיניים שלה השתנה. "בובי טבלאות? שמעתי עליך. קרה משהו אתמול ב-NexaTech, לא?" בובי לא ענה. הוא ידע לאן זה הולך. "שמעתי שמחקת טבלה חשובה," דנה המשיכה. "customers_main או משהו כזה." "זה לא בדיוק מה שקרה," בובי אמר. "הייתה בעיה עם טריגר." "בטח." דנה נשמעה לא משוכנעת. "מיכל אמרה לי שאתה רוצה להפסיק את העבודה." "יש באג בטריגר," בובי הסביר. "אם נמשיך למחוק טבלאות, זה ייצור ערכים שגויים ב-summary_tax_data." "הראה לי." בובי הראה לה את הקוד. הוא הצביע על הטעות. דנה קראה את הקוד בשקט. "זו טעות פשוטה," היא אמרה. "אפשר לתקן את זה בשניה." "נכון," בובי הסכים. "אבל צריך לוודא שהתיקון לא יוצר בעיות נוספות." דנה הביטה בו. "אתה לא סומך עליי?" "אני לא סומך על אף אחד כשזה נוגע לקוד." דנה חייכה, אבל זה לא היה חיוך חם. "בסדר. אני אתקן את הטריגר. את תמשיכי למחוק את הטבלאות." מיכל הנהנה. "בסדר." בובי לא אהב את זה. דנה רצתה לתקן את הטריגר בזמן שהוא ממשיך לעבוד. זה מסוכן. אם היא תעשה טעות, זה יכול להרוס את כל המערכת. "אני חושב שצריך להפסיק," הוא אמר. "לפחות עד שהטריגר מתוקן ונבדק." "אין לנו זמן," דנה אמרה. היא הוציאה מחשב נייד מהתיק שלה והתחילה לכתוב. "אני מתקנת את הטריגר עכשיו. זה ייקח דקה. אתה תמשיך למחוק." בובי הביט במיכל. היא נראתה לא בטוחה, אבל היא לא אמרה כלום. זו הייתה הבוסית שלה. אם הבוסית אומרת לעשות משהו, את עושה. דנה הקלידה מהר. היא פתחה את הקוד של הטריגר ושינתה את הסימן מ - ל +. "זהו," היא אמרה. "תיקנתי." "את בדקת?" בובי שאל. "לא צריך. זו טעות פשוטה. עכשיו זה נכון." בובי לא היה משוכנע. הוא רצה לבדוק בעצמו, אבל דנה כבר סגרה את המחשב הנייד. "תמשיך," היא אמרה. "מחק את temp_user_data_04." בובי הביט במסך. הוא יכול היה להתווכח, אבל זה לא יעזור. דנה הייתה בעלת הסמכות כאן. אם הוא יסרב, היא פשוט תעשה את זה בעצמה או תקרא למישהו אחר. הוא התכונן למחוק את temp_user_data_04. אבל לפני שהוא הריץ את הפקודה, הוא החליט לבדוק את summary_tax_data שוב. אם הטריגר המתוקן עובד כמו שצריך, הערכים השליליים אמורים להיעלם. הוא הריץ שאילתה שמוצאת שורות עם ערכים שליליים. המערכת החזירה עשרות שורות. הערכים עדיין שם. "הטריגר לא תיקן את הערכים הקיימים," הוא אמר. דנה הביטה במסך. "זה נורמלי. הטריגר מתקן רק נתונים חדשים. הערכים הקיימים צריכים להיות מתוקנים ידנית." "ואיך עושים את זה?" "אחרי שתסיים למחוק את הטבלאות. אין זמן לזה עכשיו." בובי לא אהב את זה, אבל הוא לא היה כאן כדי לנהל את המערכת. הוא כאן כדי למחוק טבלאות. זו העבודה. "בסדר," הוא אמר. "אני ממשיך." הוא כתב את הפקודה למחיקת temp_user_data_04. הוא הריץ אותה. המערכת התחילה לעבוד. הטריגר הופעל. בובי צפה בלוג המערכת, מחפש בעיות. הטריגר עבד. הוא בדק את summary_tax_data, מצא שורות שלא קשורות, ומחק אותן. הפעם, הוא גם עדכן ערכים. בובי ראה שהוא משנה סכומים, מאחד שורות, עושה כל מיני פעולות. ואז הוא ראה משהו מוזר. הטריגר מחק שורה שלא הייתה קשורה ל-temp_user_data_04. היא הייתה קשורה לטבלה אחרת. טבלה שנקראת permanent_tax_records. "הטריגר מוחק שורות מטבלה אחרת," הוא אמר. דנה הביטה. "איזו טבלה?" "permanent_tax_records." דנה הביטה במיכל. משהו בפנים שלה השתנה. "זו טבלה חשובה," היא אמרה בשקט. "כן," מיכל אמרה. "זו הטבלה הכי חשובה במערכת. היא מכילה את כל הרישומים הקבועים של מיסים." בובי הרגיש משהו כבד בבטן. הוא עצר את הפקודה. "אני מבטל," הוא אמר. אבל זה היה מאוחר מדי. הטבלה כבר נמחקה. הטריגר כבר הופעל. והוא כבר מחק שורות מ-permanent_tax_records. "כמה שורות נמחקו?" דנה שאלה. הקול שלה היה שקט, מבוקר. בובי בדק את הלוג. "שלוש מאות ושמונה." דנה התיישבה על כיסא. היא לא אמרה כלום למשך כמה שניות. מיכל הביטה במסך. "אולי אפשר לשחזר אותן מהגיבוי." "הגיבוי ישן שלושה ימים," דנה אמרה. "השורות שנמחקו עכשיו נוצרו היום. אין להן גיבוי." בובי ידע מה זה אומר. המידע אבד. שלוש מאות ושמונה רישומים של מיסים, נעלמו לחלוטין. אנשים שהגישו דוחות היום, נתונים שהוזנו למערכת, הכל נעלם. "למה הטריגר מחק שורות מטבלה הזו?" הוא שאל. דנה לא ענתה. היא פתחה את המחשב הנייד שלה ובדקה את הקוד של הטריגר. אחרי רגע היא אמרה, "היה קישור בין temp_user_data_04 ל-permanent_tax_records. הטריגר חשב ששורות מסוימות לא קשורות יותר לשום דבר, אז הוא מחק אותן." "אבל את תיקנת את הטריגר," בובי אמר. "תיקנתי את החישוב של הסכומים," דנה אמרה. "לא ידעתי שהטריגר גם בודק טבלאות אחרות." בובי הבין. דנה תיקנה חלק אחד של הטריגר, אבל לא בדקה את כל מה שהוא עושה. זו הייתה טעות. טעות גדולה. "אז מה עכשיו?" מיכל שאלה. דנה התבוננה במסך. "אנחנו צריכים להפסיק. לא למחוק יותר כלום. ולנסות לשחזר את השורות שנמחקו." "איך?" בובי שאל. "יש לנו לוגים. כל פעולה במערכת מתועדת. אולי אפשר לשחזר את המידע מהלוגים." זה נשמע לא מציאותי, אבל בובי לא אמר כלום. זו לא הבעיה שלו. הוא עשה מה שביקשו ממנו. מחק טבלאות. העובדה שהטריגר גרם לנזק, זו לא אשמתו. אבל הוא ידע איך זה ייראה. בובי טבלאות נקרא לרשות המסים, ושלוש מאות ושמונה רישומים נמחקו. אנשים לא יזכרו שהיה באג בטריגר. הם יזכרו שבובי היה שם כשזה קרה. דנה התבוננה בו. "אתה יכול ללכת," היא אמרה. "תודה על העזרה." בובי ידע שזו לא באמת תודה. זו הייתה דרך מנומסת להגיד "לך מפה לפני שזה יהיה יותר גרוע". הוא קם מהכיסא. "אני אשלח לכם חשבונית," הוא אמר. דנה לא ענתה. היא כבר הייתה עסוקה במשהו אחר, מנסה להבין איך לתקן את הבעיה. בובי יצא מהחדר. הוא עבר במסדרון הארוך, נכנס למעלית, וירד לחניון. המכונית שלו חיכתה שם. הוא נכנס פנימה, הדליק את המנוע, ויצא מהחניון. בדרך הביתה, הוא חשב על מה שקרה. דנה ביקשה ממנו למחוק את temp_user_data_04, והוא עשה את זה. הטריגר שהיא "תיקנה" גרם למחיקת שורות מ-permanent_tax_records. עכשיו המידע אבד, ודנה תנסה למצוא דרך לשחזר אותו. זה לא היה הפעם הראשונה שמישהו ביקש ממנו למחוק משהו ואז הכל התפוצץ. וזה לא תהיה האחרונה. כל עוד אנשים כותבים קוד עם באגים, כל עוד מערכות קורסות ומסדי נתונים מתקלקלים, תמיד יהיה צורך במישהו כמו בובי. ותמיד, כשמשהו ישתבש, הם יאשימו אותו. בובי טבלאות. מסוכן מאוד. הוא הגיע הביתה. עלה במדרגות, נכנס לדירה, והשליך את המפתחות על השולחן. הטלפון שלו התחיל לצלצל. מספר לא מוכר. הוא לא ענה. זה היה יום ארוך. הוא החליט לאכול משהו ולנסות לשכוח מהכל. מחר יהיה יום חדש, עם בעיות חדשות. ואולי, אם יהיה לו מזל, הוא לא יקבל עוד שיחות מרשות המסים. אבל משהו אמר לו שזה לא מסתיים כאן. דנה תנסה לשחזר את המידע, והיא תגלה שזה לא אפשרי. ואז היא תחפש על מי להאשים. והשם שלו, בובי טבלאות, יהיה הראשון שיעלה. הוא פתח את המקרר. לא היו בירות. הוא התכוון לקנות עוד אתמול, אבל שכח. עכשיו הוא עמד מול מקרר ריק, חושב על permanent_tax_records ועל שלוש מאות ושמונה השורות שנעלמו. הטלפון צלצל שוב. הפעם הוא הביט במסך. זה היה מספר של מיכל. הוא החליט לענות. "כן?" "בובי, זה מיכל." הקול שלה נשמע מתוח. "דנה רוצה לדבר איתך שוב. יש לה עוד משהו שהיא רוצה שתעשה." בובי לא האמין. "מה היא רוצה?" "היא רוצה שתמחק את הטבלה החמישית. temp_user_data_05." "אחרי מה שקרה?" "היא אומרת שהיא תיקנה את הטריגר עכשיו. הוא לא יגע ב-permanent_tax_records." בובי לא ידע מה לענות. דנה תיקנה את הטריגר פעם, וזה רק החמיר את המצב. עכשיו היא רוצה שהוא יסמוך עליה שוב? "אני לא חושב שזה רעיון טוב," הוא אמר. "היא מתעקשת. היא אומרת שאם לא נמחק את temp_user_data_05 עכשיו, הגיבוי ייכנס למצב עוד יותר גרוע." בובי חשב. הוא יכול לסרב. הוא יכול פשוט להגיד לא ולנתק. אבל אז דנה תמצא מישהו אחר, או שהיא תעשה את זה בעצמה. ואם משהו ישתבש, היא עדיין תאשים אותו, כי הוא זה שמחק את temp_user_data_04. או שהוא יכול לחזור, לבדוק את הטריגר בעצמו, ולוודא שהוא באמת תקין. ואז, אם הוא יחליט שזה בטוח, הוא ימחק את הטבלה. ואם לא, הוא יסרב. "אני חוזר," הוא אמר. "תודה. תודה רבה." בובי ניתק. הוא הביט במקרר הריק. הוא לא הולך לאכול עכשיו. הוא לוקח את המפתחות ויוצא שוב. הדרך חזרה לרשות המסים הייתה מהירה. פחות תנועה עכשיו. הוא הגיע לחניון, חנה, והלך למעלית. קומה שביעית, מסדרון ארוך, חדר מלא במחשבים. דנה ומיכל חיכו לו. דנה נראתה עייפה. מיכל נראתה מודאגת. "תודה שחזרת," דנה אמרה. "אני רוצה לבדוק את הטריגר," בובי אמר. "לפני שאני עושה כלום." "כמובן." דנה פתחה את המחשב הנייד שלה. "הנה. תיקנתי אותו. עכשיו הוא לא נוגע ב-permanent_tax_records." בובי קרא את הקוד. דנה הוסיפה תנאי שמונע מהטריגר לגעת בטבלאות מסוימות. זה נראה בסדר, אבל הוא לא היה בטוח. הוא רצה לבדוק את זה לעומק. "אני צריך כמה דקות," הוא אמר. "אין לנו הרבה זמן," דנה אמרה. "הגיבוי עולה בעוד עשרים דקות." "אז אני אעבוד מהר." בובי ישב מול המסכים והתחיל לבדוק את הטריגר. הוא עבר על כל שורה, מנסה להבין מה היא עושה. הקוד היה מסובך, מלא בתנאים ולולאות. דנה הוסיפה תנאי חדש, אבל בובי לא היה בטוח שהוא מספיק. הוא בדק את הקשרים בין temp_user_data_05 לבין שאר הטבלאות. היה קישור ל-summary_tax_data, מה שהיה צפוי. אבל היה גם קישור לטבלה נוספת. טבלה שנקראת secondary_records. "מה זו הטבלה הזו?" הוא שאל, מצביע על המסך. מיכל הביטה. "secondary_records? זו טבלה משנית. היא מכילה עותקים של נתונים חשובים." "למה?" "למקרה שהטבלה הראשית תתקלקל. זה גיבוי פנימי." בובי לא אהב את זה. אם secondary_records היא גיבוי, זה אומר שהיא חשובה לא פחות מהטבלה הראשית. אם הטריגר ימחק שורות משם, זה יכול להיות אסון. "הטריגר נוגע בטבלה הזו?" הוא שאל. דנה קראה את הקוד. "לא. הוספתי תנאי שמונע ממנו לגעת בטבלאות חשובות. secondary_records נכללת ברשימה." בובי בדק את התנאי. נראה שדנה צודקת. הטריגר לא אמור לגעת ב-secondary_records. אבל משהו עדיין הרגיש לא נכון. בובי בדק את הקוד שוב. והפעם הוא מצא משהו. הטריגר לא נוגע ישירות ב-secondary_records, אבל הוא קורא לפונקציה אחרת. פונקציה שנקראת cleanup_old_data. "מה הפונקציה הזו עושה?" הוא שאל. דנה הביטה. "cleanup_old_data? זו פונקציה שמנקה נתונים ישנים מהמערכת. זה רץ אוטומטית מדי יום." "והיא נוגעת ב-secondary_records?" "לא אמור." דנה נראתה לא בטוחה. בובי פתח את הקוד של cleanup_old_data. הוא קרא אותו בשקט. הפונקציה בודקת אילו שורות ב-secondary_records לא שימשו בששת החודשים האחרונים, ומוחקת אותן. "היא מוחקת שורות," הוא אמר. "רק שורות ישנות," דנה אמרה. "שלא שימשו בששת החודשים." "ואיך היא יודעת אילו שורות לא שימשו?" דנה קראה את הקוד. אחרי רגע היא אמרה, "היא בודקת אם יש להן קישור לטבלאות זמניות. אם אין, זה אומר שהן לא שימשו." בובי הבין. cleanup_old_data בודקת אם יש קישור בין secondary_records לבין הטבלאות הזמניות. אם temp_user_data_05 תימחק, הפונקציה תחשוב ששורות מסוימות ב-secondary_records לא שימשו, ותמחק אותן. "אם אני אמחק את temp_user_data_05, cleanup_old_data תמחק שורות מ-secondary_records," הוא אמר. דנה הביטה בקוד. היא קראה אותו שוב, לאט. אחרי רגע היא אמרה, "את צודקת. יש פה בעיה." מיכל נראתה מבוהלת. "אז מה עושים?" דנה חשבה. "אפשר לכבות את cleanup_old_data זמנית. אני פשוט אשנה את ההגדרות שלה כך שהיא לא תרוץ." "ואת בטוחה שזה יעזור?" בובי שאל. "כן. אם הפונקציה לא תרוץ, היא לא תמחק כלום." בובי לא היה משוכנע, אבל זו הייתה האופציה היחידה. הוא יכול לסרב למחוק את temp_user_data_05, אבל אז הגיבוי יעלה והבעיה תהיה גרועה יותר. "בסדר," הוא אמר. "כבי את cleanup_old_data, ואז אני אמחק את הטבלה." דנה פתחה את ההגדרות של cleanup_old_data ושינתה אותן. "זהו. הפונקציה מנוטרלת." בובי בדק. אכן, cleanup_old_data הייתה מוגדרת שלא תרוץ. זה נראה בטוח. הוא התכונן למחוק את temp_user_data_05. הוא כתב את הפקודה, בדק אותה, והריץ. המערכת התחילה לעבוד. הטריגר הופעל. בובי צפה בלוג המערכת. הטריגר בדק את summary_tax_data, מחק כמה שורות, עדכן אחרות. הוא לא נגע ב-permanent_tax_records. הוא לא נגע ב-secondary_records. אחרי דקה, הטבלה נמחקה. הכל נראה בסדר. "זהו," בובי אמר. "temp_user_data_05 נמחקה." דנה נשפה אויר. "תודה. תודה רבה." בובי קם מהכיסא. "אני הולך." "כן, כמובן. תודה על הסבלנות." בובי יצא מהחדר. הוא עבר במסדרון, נכנס למעלית, וירד לחניון. המכונית שלו חיכתה שם. הוא נכנס, הדליק את המנוע, ויצא. בדרך הביתה, הוא חשב על מה שקרה. הוא מחק חמש טבלאות זמניות. שלוש מהן נמחקו בלי בעיות. אחת גרמה למחיקת שורות מ-permanent_tax_records. ואחת נמחקה רק אחרי שדנה כיבתה את cleanup_old_data. זה היה יום מורכב. הוא תהה אם החשבונית שלו תשולם. כנראה שלא. רשות המסים תמצא דרך לא לשלם. הם יגידו שהוא גרם נזק, או שהעבודה לא הושלמה כמו שצריך. אבל זה לא משנה. מה שחשוב זה שהוא יודע שהוא עשה את העבודה כמיטב יכולתו. הוא בדק את הקוד, מצא באגים, אזהר את דנה. אם היא בחרה להתעלם מהאזהרות, זו הבעיה שלה. הוא הגיע הביתה. עלה במדרגות, נכנס לדירה, והשליך את המפתחות על השולחן. הטלפון שלו שקט. אין שיחות, אין הודעות. הוא פתח את המקרר. עדיין ריק. הוא החליט להזמין משהו. פיצה אולי. הוא הוציא את הטלפון וחיפש את המספר של המקום הקרוב. לפני שהוא הספיק להתקשר, הטלפון צלצל. מספר לא מוכר. שוב. הוא ענה. "כן?" "בובי טבלאות?" קול של גבר, מבוגר. "כן." "אני אבי, מנהל מערכות ב-DataCore. שמעתי עליך. יש לנו בעיה דחופה. מסד נתונים קרס, וצריך למחוק כמה טבלאות. אתה פנוי?" בובי הביט בשעון. תשע בערב. הוא רעב, עייף, ולא בטוח שהוא רוצה לעבוד עוד הלילה. "כמה אתם משלמים?" הוא שאל. "שלושת אלפים שקל לשעה." זה היה טוב. טוב מאוד. בובי חשב לרגע. "אני מגיע," הוא אמר. הוא ניתק. לקח את המפתחות, ויצא שוב. הפיצה תחכה. העבודה לא. בדרך למכונית, הוא חשב על הטריגר ב-cleanup_old_data. דנה כיבתה אותו, אבל מה אם היא תשכח להדליק אותו שוב? הפונקציה אמורה לרוץ מדי יום. אם היא לא תרוץ, נתונים ישנים יצטברו, והמערכת תתמלא. אבל זו לא הבעיה שלו. הוא עשה מה שביקשו ממנו. השאר תלוי בדנה. הוא נכנס למכונית והתניע את המנוע. DataCore נמצאת בצד השני של העיר. זה ייקח לו עשרים דקות להגיע. הוא יכול להתחיל את העבודה שם בעשר, לסיים בחצות, ולחזור הביתה. יום ארוך. אבל זו העבודה. בובי טבלאות. מפיל טבלאות. מסוכן מאוד. --- הוא נסע ברחובות השקטים. רדיו כבוי, חלון קצת פתוח. אוויר קריר נכנס, מה שעזר לו להישאר ערני. הוא חשב על מה שקרה היום. שתי עבודות. אחת ב-NexaTech, שם טבלת לקוחות נמחקה בגלל טריגר שגוי. ועכשיו ברשות המסים, שם שלוש מאות ושמונה רישומים נעלמו, שוב בגלל טריגר. טריגרים הם בעיה. הם מסובכים, קשה לבדוק אותם, וכשהם נכשלים, הנזק גדול. בובי לא אוהב טריגרים. הוא מעדיף קוד פשוט, ישיר, שאפשר לקרוא ולהבין. אבל אנשים אוהבים לכתוב קוד מורכב. הם חושבים שזה הופך אותם לחכמים. והם לא מבינים שכל שורה נוספת של קוד היא עוד מקום שבו משהו יכול להישבר. הוא הגיע ל-DataCore. בניין נמוך, מודרני, עם חניון גדול. הוא חנה ליד הכניסה ויצא מהמכונית. איש חיכה לו ליד הדלת. גבר מבוגר, שיער אפור, משקפיים עבים. הוא נראה לחוץ. "בובי?" הוא שאל. "כן." "אני אבי. תודה שבאת כל כך מהר." הוא הושיט יד. בובי לחץ עליה. "בואו נתחיל," בובי אמר. אבי הנהן והוביל אותו לתוך הבניין. הם עלו לקומה השנייה, עברו במסדרון, והגיעו לחדר קטן עם שולחן אחד ומחשב אחד. "זה המחשב שמחובר לשרת," אבי אמר. "יש לך גישה מלאה." בובי התיישב. הוא הביט במסך. ממשק פשוט, ללא קישוטים. טוב. הוא העדיף לעבוד עם ממשקים פשוטים. "אז מה הבעיה?" הוא שאל. אבי הסביר. "השרת שלנו קרס אחרי עדכון כושל. יש שלוש טבלאות שנשארו במצב לא עקבי. צריך למחוק אותן כדי שנוכל להריץ את העדכון מחדש." בובי הנהן. זה נשמע מוכר. בדיוק כמו ב-NexaTech. עדכון כושל, טבלאות לא עקביות, צורך למחוק. "איזה טבלאות?" הוא שאל. אבי פתח קובץ טקסט. "migration_temp_01, migration_temp_02, ו-migration_backup." בובי קרא את השמות. הם נראו סטנדרטיים. הוא התחבר למסד הנתונים עם הפרטים שאבי נתן לו. המערכת הייתה קטנה. רק כמה עשרות טבלאות. הרבה יותר קטנה מרשות המסים. זה היה טוב. פחות מקום לטעויות. הוא חיפש את migration_temp_01. היא הייתה שם. הוא בדק את המבנה שלה. פשוט. שדות בסיסיים, ללא קשרים חיצוניים. "יש טריגרים?" הוא שאל. "לא." אבי היה בטוח. "הטבלאות האלו הן פשוט זמניות. אין להן טריגרים." בובי בדק בעצמו. אכן, אין טריגרים. זה טוב. אחרי מה שקרה היום, הוא לא רצה לראות עוד טריגרים. הוא התכונן למחוק את migration_temp_01. הוא כתב את הפקודה, בדק אותה, והריץ. הטבלה נמחקה תוך שניות. "אחת נעשתה," הוא אמר. אבי נראה מרוצה. "מעולה. תמשיך." בובי עבר ל-migration_temp_02. אותו תהליך. בדיקה, פקודה, מחיקה. הכל עבד בצורה חלקה. "שתיים," הוא אמר. הוא עבר לטבלה השלישית. migration_backup. הוא בדק את המבנה שלה. היא הייתה גדולה יותר מהשתיים הראשונות. עשרה גיגה של מידע. "למה הטבלה הזו כל כך גדולה?" הוא שאל. "היא מכילה גיבוי של הנתונים לפני העדכון," אבי הסביר. "במקרה שהעדכון ייכשל, אנחנו יכולים לשחזר מהגיבוי." "והעדכון כבר נכשל, אז למה למחוק את הגיבוי?" "כי אנחנו הולכים להריץ את העדכון מחדש. הגיבוי הישן לא רלוונטי יותר." זה נשמע הגיוני, אבל בובי לא היה בטוח. מחיקת גיבוי זה תמיד מסוכן. מה אם העדכון ייכשל שוב? אז לא יהיה גיבוי לחזור אליו. "יש לכם גיבוי אחר?" הוא שאל. "כן. יש לנו גיבוי חיצוני שנעשה לפני יומיים." "רק יומיים?" "כן." בובי חשב. יומיים זה לא רע. אם העדכון ייכשל, הם יכולים לחזור לגיבוי החיצוני ולאבד רק יומיים של נתונים. "בסדר," הוא אמר. "אני ממשיך." הוא כתב את הפקודה למחיקת migration_backup. המערכת התחילה לעבוד. זה לקח זמן, כי הטבלה הייתה גדולה. בובי חיכה, צופה בלוג המערכת. אחרי כמה דקות, הטבלה נמחקה. "זהו," בובי אמר. "שלוש הטבלאות נמחקו." אבי נשף אויר. "תודה. תודה רבה. עכשיו אנחנו יכולים להריץ את העדכון מחדש." בובי התנתק מהמערכת. הוא קם מהכיסא. "אני אשלח לך חשבונית מחר," הוא אמר. "בטח. אין בעיה." בובי יצא מהחדר. הוא עבר במסדרון, ירד במדרגות, ויצא מהבניין. המכונית שלו חיכתה שם. הוא נכנס והתניע את המנוע. העבודה הסתיימה. פשוטה, מהירה, ללא בעיות. בדיוק כמו שצריך להיות. בדרך הביתה, הוא חשב על ההבדל בין העבודה ב-DataCore לבין העבודה ברשות המסים. ב-DataCore לא היו טריגרים. הטבלאות היו פשוטות, ברורות. הכל עבד כמו שצריך. ברשות המסים, זה היה הפוך. טריגרים מסובכים, קשרים לא ברורים, קוד שאף אחד לא באמת הבין. והתוצאה הייתה אסון. זה מה שבובי למד במהלך השנים. מערכות פשוטות עובדות טוב יותר. קוד פשוט עובד טוב יותר. כל פעם שמישהו מנסה להיות חכם מדי, זה מסתיים רע. הוא הגיע הביתה. עלה במדרגות, נכנס לדירה, והשליך את המפתחות על השולחן. הטלפון שלו שקט. טוב. הוא לא רצה עוד שיחות הלילה. הוא פתח את המקרר. עדיין ריק. הוא החליט להזמין משהו. פיצה. הוא התקשר למספר שהכיר, הזמין פיצה גדולה עם גבינה ופטריות. בזמן שהוא חיכה לפיצה, הוא התיישב על הספה וחשב על היום. שלוש עבודות. NexaTech, רשות המסים, ו-DataCore. אחת הסתיימה רע, אחת הסתיימה ממש רע, ואחת הסתיימה טוב. לא יום רע בסך הכל. אם החשבונית מ-DataCore תשולם, זה יכסה את מה שהוא לא יקבל מ-NexaTech ורשות המסים. הפיצה הגיעה. הוא פתח את הדלת, שילם למשלוח, ולקח את הקופסה. הוא התיישב ליד השולחן ואכל לאט. הפיצה הייתה טובה. לא מעולה, אבל טובה. אחרי האוכל, הוא התקלח והלך לישון. המיטה הייתה קשה, אבל הוא התרגל אליה. הוא שכב במשך כמה דקות, מביט בתקרה, חושב על permanent_tax_records ועל שלוש מאות ושמונה השורות שנעלמו. ואז הוא נרדם. לא היו חלומות. רק שינה שחורה ושקטה עד הבוקר. בבוקר, הטלפון שלו צלצל. הוא פתח עין אחת והביט בשעון. שמונה וחצי. הוא הרים את המכשיר והביט במסך. מספר של מיכל. הוא לא ענה. הוא סגר את העין וניסה לחזור לישון. הטלפון צלצל שוב. ושוב. ושוב. בסוף, הוא לחץ על כפתור הקבלה. "כן?" הקול שלו היה מחוספס. "בובי, זה מיכל. יש לנו בעיה." בובי התיישב על המיטה. "מה עכשיו?" "cleanup_old_data התחילה לרוץ אוטומטית הבוקר. דנה שכחה שהיא כיבתה אותה. המערכת הדליקה אותה בחזרה אוטומטית." בובי ידע לאן זה הולך. "ו?" "והיא מחקה שורות מ-secondary_records. אלפי שורות." בובי לא אמר כלום. הוא ידע שזה יקרה. cleanup_old_data הייתה מוגדרת לרוץ מדי יום. כשדנה כיבתה אותה אתמול, זה היה רק זמני. הבוקר, המערכת הדליקה אותה בחזרה. "כמה שורות נמחקו?" הוא שאל. "ארבעת אלפים ומאתיים." זה היה גרוע. גרוע מאוד. secondary_records הייתה טבלת גיבוי. אם אלפי שורות נמחקו משם, המערכת נמצאת בסכנה. "מה את רוצה ממני?" בובי שאל. "דנה רוצה לדבר איתך. היא אומרת שאתה אחראי." בובי לא האמין. "איך אני אחראי? אני לא כיבתי את cleanup_old_data. דנה עשתה את זה." "היא אומרת שאתה ידעת שזה יכול לקרות. ושלא אזהרת אותה." "אזהרתי. אמרתי לה שהפונקציה תמחק שורות אם נמחק את temp_user_data_05." "היא אומרת שלא הבנת את זה נכון. שטעית." בובי נאנח. זה תמיד ככה. כשמשהו משתבש, אנשים מחפשים על מי להאשים. והוא תמיד השד הקלה. "תגידי לדנה שאני לא אחראי," הוא אמר. "היא כיבתה את cleanup_old_data. היא צריכה הייתה לוודא שהיא לא תידלק בחזרה." "היא לא מקבלת את זה. היא רוצה שתחזור ותתקן את הבעיה." "איזו בעיה? השורות נמחקו. אין דרך לשחזר אותן." "יש לוגים. אולי אפשר לשחזר מהלוגים." בובי חשב. אולי. זה תלוי באיכות הלוגים ובכמות המידע שהם מכילים. אבל זה יהיה עבודה ארוכה, מסובכת, וללא ערובה להצלחה. "תגידי לדנה שאני לא חוזר," הוא אמר. "היא צריכה למצוא מישהו אחר." "בבקשה, בובי. אנחנו צריכים את העזרה שלך." "לא." בובי היה נחוש. "עשיתי את העבודה שביקשתם. השאר תלוי בכם." הוא ניתק. הטלפון צלצל שוב מיד, אבל הוא לא ענה. הוא כיבה את המכשיר והשליך אותו על השידה. הוא קם מהמיטה, התקלח, ולבש בגדים נקיים. היום הוא לא הולך לעבוד. היום הוא הולך לנוח. אבל משהו לא נתן לו לשכוח. secondary_records. ארבעת אלפים ומאתיים שורות. זה הרבה מידע. אנשים שהגישו דוחות, נתונים שהוזנו למערכת, הכל נעלם. והוא היה שם כשזה קרה. לא ישירות, אבל הוא היה חלק מהשרשרת של אירועים שהובילה לזה. בובי טבלאות. מפיל טבלאות. גם כאלו שלא אמור למחוק. הוא הלך למטבח ושתה מים. הוא הביט מהחלון על העיר. בניינים אפורים, שמיים מעוננים. יום רגיל. הטלפון שלו צלצל שוב. הוא הדליק אותו והביט במסך. מספר לא מוכר. הוא ענה. "כן?" "בובי טבלאות?" קול של גבר צעיר. "כן." "שמעתי עליך מחבר. יש לנו בעיה עם מסד נתונים. אתה פנוי?" בובי חשב לרגע. הוא יכול לסרב. לנוח. לשכוח מהכל. או שהוא יכול להמשיך. עוד עבודה, עוד טבלאות, עוד בעיות. "כמה אתם משלמים?" הוא שאל.

Comments (0)

No comments yet. Be the first to share your thoughts!

Sign In

Please sign in to continue.