הבלוג של ארתיום
בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא!
MySQL אכן צעצוע - או rollback לא עובד בצורה מסתורית על InnoDB
עידו, מאיר, שי - אתם צודקים! MySQL אכן צעצוע!
תוך כדי הרצת Unit Test של עבודה מול ODBC גיליתי שטרקציות לא מבצעות roolback. מידי הבנתי ששכחתי להגדיר את הטבלה כ־InnoDB והרצתי את הטסט שוב עם טבלה חדשה. עדיין נכשל. WTF? נכנסתי ללקוח של MySQL והרצתי:
create table test ( i integer ) Engine = InnoDB;
begin;
insert into test(i) values(10);
insert into test(i) values(20);
rollback;
select count(*) from test;
ואני מקבל כפלט 2 במקום 0? WTF $%^$%^&#$%^#&^#%&?
פניתי ל־Stackoverflow אולי אני עושה משהו לא נכון וקיבלתי תשובה: הקוד שלי בסדר גמור.
אולי גרסת בסיס נתונים ישנה 5.0.51? התקנתי 5.1.49 עדיין אותה בעיה! ניסיתי לחזור ל־5.0.51 סקריפט של dpkg נכשל! משהו פה ממש לא בסדר.
מחקתי את בסיס הנתונים עם Purge - קרי מחקתי התקנה, הגדרות ואת כל בסיסי הנתונים, התקנתי 5.0.51 מחדש ו... זה אכן עובד.
המזל שמדובר בבסיס הנתונים של פיתוח, נכנסתי לבסיס הנתונים של ייצור, הרצתי את הבדיקה זה עבד. יכולתי לנשום קצת לרווחה.
עידו, מאיר, שי אנשים יקרים: אתם צודקים... MySQL זה צעצוע.
עכשיו השאלה - כיצד אני מכייל את PostgreSQL לביצועים דומים? :-)
בניות ובדיקות ליליות ו־VirtualBox
כל מי שמפתח פרויקט מורכב שתומך במספר רב של פלטפורמות יודע עד כמה זה קשה להוציא גרסה בדוקה שתעבוד בכל אחת מהן.
נכון, כולנו ;)
כותבים טסטים אוטומטיים ודואגים שהם יעברו בשלום לפני שחרור הגרסה, אבל... זה לא תמיד מספיק כי תמיד משהו איפשהו נשבר ולפי חוק מרפי משהו יישבר דווקא במקודם שלא עשית בו בדיקה נוספת.
כנ"ל CppCMS, אפילו שיש לי מערכת Unit-Tests שלמה, מידי פעם יש פספוסים בשחרור גרסה. וזה ברור: כשאתה מנסה לתמוך ב־GCC החל מ־3.4 עד 4.5, בקומפיילר של MSVC ושל Intel ב־Solaris, Linux, BSD, Mac OS X ו־Windows אז משהו בתוך כ־40 אלף שורות קוד חייב להישבר.
אז כבר הרבה זמן אני מחזיק מספר מערכות הפעלה על VirtualBox כדי לבצע בדיקות מידי פעם, רק שהפעם, הבנתי שהגיע זמן למכן את התהליך. ובכן, יצרתי מערכת Build לילית שבונה גרסה נקייה מ־trunk ומריצה טסטים. זה יחסית פשוט כאשר מדובר במכונה מקומית, ויש אפילו מערכות מוכנות לזה, אבל כשצריך לשלב מספר מערכות פעלה וסביבות וירטואליות, זה כבר קצת יותר מסובך.
בכל מקרה, בניתי סקריפט, שרץ מתוך crontab ומעלה מכונה וירטואלי, מתחבר אליה דרך ssh מריץ תסריט בניה וטסט ואז מוריד אותה באופן אוטומטי וכך לכל למכונה (למעשה Solaris ו־FreeBSD).
כאשר ניסיתי לעשות את אותו הטריק עם XP הסיפור הפך להיות מתסכל, בשרת FreeSSHD פשוט לא הצלחתי לבצע password-less login על־אף מאמצים רבים וקריאת התיעוד. בכל מקרה, המוצר הזה השאיר לי תחושה של מוצר "חצי־אפוי" כי הוא לא תמיד התנהג כמו שהוא אמור.
אחר־כך ניסיתי copssh, גם הוא היה כישלון טוטלי מכיוון שלא הצליח להעלות סרביס של ssh עם הודעות שגיאה על הרשאות ומשתמש ב־Even Log. החיפושים ברשת לא הניבו תוצאות. אז עברתי לגישה אחרת.
העתקתי את התסריט וכל הקבצים הנדרשים לשרת Samba והכנתי תסריט bat שרץ בחלונות וניגש תיקיה עם עליית המערכת. אם הקובץ נמצא, הוא בונה גרסה ומריץ טסטים, לאחר מכן שם את התוצאות באותו שרת ה־samba. עקום, אבל איכשהו עובד (כמו כל דבר אחר בחלונות...)
וכך נולדה מערכת בניה ובדיקות ליליות של CppCMS שמבצעת בדיקה על מספר פלטפורמות ומייצרת דו"ח יומי. בדיוק בגלל הדברים האלה אתה מבין עד כמה וירטואליזציה היא דבר אדיר.
CppCMS מול Java/JSP, C#/Asp.Net, PHP
פרסמתי השוואת ביצועים עדכנית בין CppCMS ושלוש טכנולוגיות web מובילות: PHP, Asp.Net/Mono ו־Java/JSP.
התוצאות וההסברים פורסמו כאן: http://art-blog.no-ip.info/cppcms/blog/post/67
BiDiTeX 0.0.9 - כש־ABI נשבר
שוחררה גרסת biditex החדש 0.0.9.
שינויים:
- התאמה לגרסה 0.19.x של FriBiDi
- תמיכה בנוסחאות המוגדרות ע"י
\[
ו־\]
.
הסיבה: ספריית fribidi שברה את ה־ABI ואת ה־API שלה בלי לעדכן נכון את הגרסה ותיעוד, מה שגרם לי לא מעט כאב ראש ויצירת גרסת BiDiTeX חדשה.
שימו לב, אם biditex נשבר בצורה לא ברורה או לא מתפקד בצורה מוזרה, תורידו בבקשה חבילה עדכנית, או תקמפלו אותו מחדש מול גרסת fribidi עדכנית 0.19.x, הגרסאות שקומפלו עם fribidi הישן לא יעבדו לכם.
אז תעדכנו בבקשה את גרסת ה־biditex שלכם. שימו לב, החבילות שניתנות להורדה מ־sourceforge קומפלו בצורה סטטית ולא אמורות להישבר.
להורדה כרגיל, באותו מקום: http://sourceforge.net/projects/biditex/files/
יצירת מספרים אקראיים עם /dev/urandom וכמה קל ליפול בפח
רובינו מכירים את /dev/urandom
הנפלא שמאפשר לייצר מספרים אקראיים בטוחים מבחינה קריפטוגרפית במהירות רבה.
למשל, אנחנו רוצים ליצור session-id חדש, מה קל יותר? פונים ל־/dev/urandom
ומקבלים בשפע.
אבל כשבפועל השתמשתי בו ליצירת session-ids בגודל של 16 בתים, גיליתי... הוא מאוד אטי... הצלחתי לייצר משהו כמו 1,100 כאלה בשנייה, לא הרבה. התחלתי להתחכם, יצרתי מספר אחד להתחלה, הוספתי לו כמה שדות כמו זמן, מספר, לקחתי לו איזה md5 ואז זה עבד יפה וגם מהר (למרות שהמספרים האלה לא באים באותה איכות כמו שיכולתי לקבל אותם מ־/dev/urandom
.
יום אחד בהיר הסתכלתי בקוד של Boost.UUID וראיתי שבקוד שלו, במקום להשתמש בפונקציות סטנדרטיות ופשוטות כמו std::ifstream או fopen פותחים את הקובץ ישירות עם open של מערכת ההפעלה וקוראים אותו עם read. מוזר, עשיתי בדיקה קצרה ו... זה קיבלתי 110,000 מפתחות של 16 בתים בשנייה במקום 1,100 - הבדל של שני סדרי גודל!
מה קורה פה?
אחרי מחקר קצר גיליתי ש:
FILE *f=fopen("/dev/urandom","r");
setbuf(f,0);
char buf[16];
fread(buf,1,16,f);
fclose(f);
עובד מהר מאוד, אבל אם מוחקים את השורה השנייה setbuf(f,0)
מגלים שהוא הופך לאטי להחריד.
הסבר: ביטל של buffer פנימי בעזרת setbuf(), גורם לכך, שכל פניה לקריאה מהקובץ מתבצעת בדיוק במספר הבתים שביקשנו. אבל, כאשר buffer מוגדל, הספרייה הסטנדרטית מבצעת תחכום ומנסה לקרוא כמה שיותר (למעשה 4K) ובפועל במקום לקרוא מ־/dev/urandom
16 בתים, היא קוראת 4096...
מוסר השכל: אם אתה פותח /dev/urandom
תמיד וודא שאתה לא משתמש ב־buffering בספריה שלך!