חושבים שאתם מגבים כמו שצריך?
26/01/2008 10:40 ע"י כתריאל טראוםאתם לא יכולים להיות בטוחים עד שלא תעברו את ההכשרה על "שבעת ראשי הגיבוי" לפי תורת הטאו של הגיבויים: כיסוי, תדירות, הפרדה, היסטוריה, בדיקה, אבטחה ושלמות המידע.
אתם לא יכולים להיות בטוחים עד שלא תעברו את ההכשרה על "שבעת ראשי הגיבוי" לפי תורת הטאו של הגיבויים: כיסוי, תדירות, הפרדה, היסטוריה, בדיקה, אבטחה ושלמות המידע.
עם העבודה על jiyuu, יוצא לי לא מעט לעבוד עם sqlite. למי שלא מכיר, זה מסד נתונים אשר מיושם בספריה, ללא שרת, ללא צורך בהתקנה ועם תמיכה ב-Transactions.
סכמת מסד הנתונים של jiyuu אינה מסובכת כל כך. היא כוללת כמה טבלאות פשוטות שמחזיקות פוסטים, תגובות, תגיות וקונפיגורציה. אבל, למרות הפשטות, היה חסר לי מאפיין אחד חשוב, שיעזור לי לשמור על הנקיון ועל תקינות המידע: Foreign Keys.
הסבר מהיר: Foreign Keys הוא מנגנון במסדי נתונים שמאפשר יצירת קשר בין טבלאות שונות. בעזרת Foreign Key ניתן לקשר מידע בטבלה א' למידע בטבלה ב' כך שלא יכול להיות מידע בעמודה מקושרת בטבלה א' שאינו קיים בטבלה ב'. קישור זה הוא בד"כ דו-כיווני: לא ניתן יהיה למחוק מידע מטבלה ב', כל עוד ישנם רשומות בטבלה א' שעדיין מפנות אליה.
דוגמא:
CREATE TABLE tbl1 ( id INTEGER PRIMARY KEY NOT NULL, col1 VARCHAR(20), col2 INTEGER NOT NULL CONSTRAINT fk_tbl2_id REFERENCES tbl2(id))
זהו התחביר ליצירת Foreign Keys ב-SQLite (אפילו שהוא לא תומך ב-Foreign Keys. עוד על זה מיד). לפי הדוגמא, לא ניתן יהיה להכניס שורה חדשה לטבלה tbl1, במידה והערך של col2 לא יהיה קיים ב-tbl2. בכיוון השני, ברגע שיש מידע שבטבלה tbl1 אשר מקושר ל-tbl2, לא ניתן יהיה למחוק את הרשומה שאליה המידע קשור ב-tbl2.
רק רגע, אבל הרגע אמרתי ש-Foreign Keys לא נתמך ב-SQLite. המצב כרגע הוא שהפקודות קיימות, אך SQLite לא מתייחס אליהם או עושה להם Parsing\Enforcing. אז איך כן ניתן ליישם Foreign Keys שישמרו על אחידות המידע שלי? התשובה פשוטה: Triggers
הפוסט הזה הופך לשעור ב-SQL… אז מה זה Triggers? אלו פקודות SQL אשר מורות למסד הנתונים לבצע פקודה מסויימת כאשר מתרחש מקרה מסויים. ניתן לנצל יכולת זו כדי לתפוס כל מחיקה, יצירה או שינוי של רשומה כדי לוודא שאין התנגשות עם Foreign Key. נצטרך לצור 3 Trigger-ים: אחד עבור יצירה, מחיקה ועדכון רשומה, בעבור כל טבלה שבא הגדרנו Foreign Key Constraint
CREATE TRIGGER fk_insert_tbl1
BEFORE INSERT ON tbl1
FOR EACH ROW BEGIN
SELECT RAISE(ROLLBACK, 'insert on table "tbl1" violates foreign key constraint "fk_insert_tbl1"')
WHERE (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL;
END;
CREATE TRIGGER fk_update_tbl1
BEFORE UPDATE ON tbl1
FOR EACH ROW BEGIN
SELECT RAISE(ROLLBACK, 'update on table "tbl1" violates foreign key constraint "fk_update_tbl1"')
WHERE (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL;
END;
CREATE TRIGGER fk_delete_tbl2
BEFORE DELETE ON tbl2
FOR EACH ROW BEGIN
SELECT RAISE(ROLLBACK, 'delete on table "tbl2" violates foreign key constraint "fk_delete_tbl2"')
WHERE (SELECT col2 FROM tbl1 WHERE col2 = OLD.id) IS NOT NULL;
END;
הרבה מידע, אני יודע. אבל אם מתעמקים טיפה, לא מסובך מדי. 2 הדוגמאות הראשונות בעצם דואגות כי לפני יצירה\שינוי ב-tbl1, ייבדק כי קיים ערך מתאים ב-tbl2. הדוגמא השלישית פועלת בכלל על tbl2 בזמן מחיקת רשומה, ומוודאת כי אין רשומות מקושרות ב-tbl1. שימו לב כי אם השדה col2 ב-tbl1 לא היה מוגדר כ-NOT NULL, הפלט היה קצת אחר, אם לדוגמא ניקח את ה Insert Trigger הבא:
CREATE TRIGGER fk_insert_tbl1 BEFORE INSERT ON tbl1 FOR EACH ROW BEGIN SELECT RAISE(ROLLBACK, 'insert on table "tbl1" violates foreign key constraint "fk_insert_tbl1"') WHERE NEW.col2 IS NOT NULL AND (SELECT id FROM tbl2 WHERE id = NEW.col2) IS NULL; END;
התוספת היא השורה WHERE NEW.col2 IS NOT NULL, אשר מוודא כי השדה החדש אינו ריק לפני שה-Foreign Key נאכף.
למחפשים עוד מידע, את הדוגמאות שלי שאבתי מהקישור הבא, והשתמשתי בכלי הבא כדי לייצר Triggers מה-Foreign Keys שלי.
אז עכשיו יש ל-jiyuu מסד נתונים מסודר, נקי ונכון. וכדי להפוך את הסכמה לקריאה יותר, השארתי את פקודות ב-Foreign Key המקוריות.
אז יש לכם כמה שרתים לנהל? אולי כמה עשרות? אתם בטח משתמשים ב- SSH Private/Public key בשביל להזדהות בהתחברות אליהם, זה מה שאני הייתי עושה.
אם זה המצב, סדר הפעולות הבא בודאי לא זר לכם. העתקת המפתח, התחברות למכונה, העברה ל-authorized_keys, מחיקת המפתח. מיגע.
$ scp .ssh/id_dsa.pub 192.168.1.10:~/ Password: id_dsa.pub 100% 604 0.6KB/s 00:00 $ ssh 192.168.1.10 Password: . katriel@server1:~$ cat id_dsa.pub >> .ssh/authorized_keys katriel@server1:~$ chmod 700 .ssh katriel@server1:~$ chmod 600 .ssh/authorized_keys katriel@server1:~$ rm id_dsa.pub katriel@web-vm:~$ logout Connection to 192.168.22.107 closed. $ ssh 192.168.1.10 katriel@server1:~$
אז אל דאגה. לעזרתנו מגיע הכלי ssh-copy-id, שעושה את הנ"ל, בפקודה אחת:
$ ssh-copy-id -i ~/.ssh/id_dsa.pub 192.168.1.10 34 Password: Now try logging into the machine, with "ssh '192.168.1.10'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. $ ssh 192.168.1.10 katriel@server1:~$
קצר ולעניין, אני לא חשוב שיש צורך בהסברים מיותרים. תהנו!
עם השחרור הממשמש ובא של lighttpd 1.5 החלטתי לבדוק את הסחורה.
ניסיתי להשתמש בחבילות שקומפלו מראש עבור Sarge, אבל היה קצת בעיות עם תלויות, לכן החלטתי להוריד את חבילת המקור ולקמפלה מחדש עבור Etch. מי שרוצה לנסות את החבילות המקומפלות, מוזמן להוריד את החבילות ולנסות.
מכיוון שאני משתמש ב-lighttpd שרץ ב-VM תחת lguest כדי לפתח את jiyuu, הדבר הראשון שניגשתי לעשות הוא לקנפג את lighttpd לעבוד עם fast-cgi/php. כמובן שאי אפשר להוציא גירסא חדשה אם לא שוברים לפחות דבר אחד או שניים בתאימות לאחור.
בדיקה מהירה הראתה כי המודול mod_fastcgi הוחלף ב-mod_proxy_core עם תוספת של קצת mod_proxy_backend_fastcgi בצד. במקום ליישם מודול נפרד, התמיכה ב-FastCGI הועברה לתת-מודול של mod_proxy אשר תומך לא רק ב-FastCGI אלא גם ב-scgi, http ו- ajp. מתוחכם.
הבעיה היחידה, או יותר נכון "חוסר הנוחות" שהשינוי יוצר, הוא ש-lighttpd לא יעשה יותר spawning של php-cgi בשבילנו, צריך לעשות את העבודה לבד. לצורך כך, נצטרך להשתמש בפקודה "spawn-fcgi" ולשתול אותה בתסריט האתחול של lighttpd, עוד על כך מייד.
עם שינוי השיטה, שונתה גם הקונפיגורציה כמובן. הקונפיגורציה החדשה להפעלת php ב-FastCGI נראית כך:
server.modules += ("mod_proxy_core", "mod_proxy_backend_fastcgi")
$PHYSICAL["existing-path"] =~ "\.php$" {
proxy-core.balancer = "round-robin"
proxy-core.protocol = "fastcgi"
proxy-core.allow-x-sendfile = "enable"
proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
proxy-core.max-pool-size = 5
proxy-core.rewrite-request = (
"_pathinfo" => ( "\.php(/.*)" => "$1" )
)
}
ההסתמכות על mod_proxy מאפשרת ל-lighttpd להשתמש ביכולת המובנית של load balancing דרך socket מקומי או מעל הרשת.
הקטע הטריקי הוא כמובן התוספת של העלאת FastCGI עם העליה\ירידה של lighttpd. הקובץ הבא הוא התאמה של תסריט האתחול עבור דביאן 4.0 (Etch), ומכיל את התוספת הדרושה כדי להעלות את php-cgi.
התוספת היא די פשוטה וברורה, לכן לא תהיה בעיה להעתיקה לתסריטי אתחול בהפצות אחרות. בפונקציה start יש להוסיף הפקודה הבאה:
/usr/bin/spawn-fcgi -s /tmp/php-fastcgi.sock \ -f /usr/bin/php-cgi -u www-data -g www-data -C 5 -P /var/run/spawn-fcgi.pid
בעוד לפונקציה stop נוסיף משהו בסגנון של:
kill `cat /var/run/spawn-fcgi.pid` if [ -f /tmp/php-fastcgi.sock ]; then /bin/rm -f /tmp/php-fastcgi.sock; fi if [ -f /var/run/spawn-fcgi.pid ]; then /bin/rm -f /var/run/spawn-fcgi.pid; fi
לא משהו, אחרי שהורגלתי לטוב בגירסא 1.4, אבל אפשר לחיות עם זה.
עכשיו אפשר להתחיל לבדוק את שאר החידושים ושיפורי הביצועים בגירסא 1.5. תהנו!
אחרי ההצהרה הראשונה על מפת דרכים ל-RPM5, שוחרה לאחרונה הגירסא הסופית. RPM5 הוא גירסא חדשה של RPM הותיק שקיים כבר מאז 1997. RPM התחיל את דרכו כ-Red Hat Package Manager, אבל כיום, הוא ראשי תיבות רקורסיביים: RPM Package Manager, כמו שכל כך אהוב אצלנו בעולם הקוד הפתוח.
גירסא 5 כוללת שיפורים כמו שכתוב קוד המקור לתמיכה בעוד מערכות הפעלה: Soalris, BSD ו-MacOSX, כל אלו כמובן, בתוספת לסביבה הטבעית שלו, לינוקס. מפתחי גירסא 5 טוענים לשיפור ביצועים; פעולות התקנה ושאילתות אמורות להיות פי-10 מהירות יותר. קבצי ה-SPEC שופרו, וכוללים היום אופציה להורדה של קבצי המקור בזמן בניית ה-RPM ועוד. תמיכה ב-RPMv3 הוסרה, מה שמוריד סיבוכיות וכמות קוד מהפרויקט.
כל זה נשמע מצויין, אבל אליה וקוץ בה, RPM5, כך טוענת רד-האט, היא בעצם Fork של RPM בגירסא 4, שלטענת רד-האט והפצ(צ)ות אחרות אשר משתמשות ב-RPM, היא הגירסא הרשמית. בנוסף, אומרת רד-האט, כי אין בכוונתה או בכוונת פרויקט פדורה לעבור להשתמש בגירסא 5 של RPM.
שני האתרים טוענים כי הם ה"גירסא הרשמית" של ה-RPM Code base, אבל יותר נכון הוא ש-RPM5 מבוסס על RPM4. המפתחים של RPM5 טוענים כי הם מקפידים לשמור על תאימות מלאה עם RPM4, ואף מכניסים קוד ותיקונים מ-RPM4 לגירסא 5.
אז מי הרשמי? מי המתחזה? סביר להניח, שכמו תמיד, מבוסס פה כל הסיפור על יוקרה ויריבות. את RPM4 מפתחת רד-האט בעיקר, בשיתוף עם שאר ההפצות מבוססות RPM כמו סוסה ומנדריבה. את RPM5 מנהיג אחד המפתחים לשעבר של RPM4 אשר עבד ברד-האט והיה חלק מפיתוחו של RPM4. את המסכנות תסיקו לבד.
אישית, אני מקווה שרד-האט ושות' כן ישקלו לאמץ את RPM5, או לפחות חלק מה-features שלו. אחרי קצת משחקים ונסיונות, הוא אכן מרגיש הרבה יותר חלק ומהיר. עוד לא התעמקתי בקבצי ה-SPEC המחודשים, אבל בהחלט נראה שיש התקדמות.
במיוחד קורצת לי התמיכה בריבוי פלטפורמות. לאחר נסיון עבר בכתיבת חבילות (למזלי החבילות ארזו אך ורק סקריפטים) לרד-האט וסולאריס, אני יכול להגיד שזו לא חויה מרנינה במיוחד.