ארכיון חודשי: פברואר 2012

WAT I have learned about …

בשבוע האחרון יצא לי לעשות הרבה דברים שונים.

למשל לכתוב קצת קוד פיתון, ולגלות כי Tuple זו הגדרה מוזרה במקצת:

a = (1)  # an Integer
a = (1,) # a Tuple
a = 1    # an integer
a = 1,   # a Tuple

על זה נאמר WAT ?

אבל זה לא הכל.
המרתי תוכנה שלי מרובי 1.8.7, שרצה כבר מספר שנים ב production לגרסה 1.9.3.
החדשות הטובות הן כי כמעט כל הקוד שלי עובד בלי שינוי. החדשות הרעות הן, שרק דבר אחד לא באמת עבד בתחביר:

case a
 when 1 : something # 1.9.3 raises syntax error
 when 1
          something # Both 1.8.7 and 1.9.3 accept it
end

ואם זה לא מספיק בעייתי, גיליתי על מספר תחבירי פסקל מונחה עצמים שהייתי בטוח שאני יודע ומכיר, ומסתבר כי אני לא משתמש בהם נכון, ועבדתי סתם קשה איתם (ועוד יש אנשים שלא יודעים בכלל, ויש להם רעיונות כמה שהם כן יודעים לגבי השפה). להמשיך לקרוא

Yes SQL, No SQL

Freedom-of-choiceUnlike the attempt to picture things, the idea of non SQL based databases exists for many years.

The thing is, that sure SQL based databases are important, but they are not the only means to use. You need to better understand your needs before you choose the proper way to store and retrieve data.  "NoSQL" is not the answer for life, universe and everything (that's 42), but it's another way to look at your data.

It's not always possible to use the same structure to handle data. Sometimes your data structure is way too simple to use SQL, Sometimes it's too complicated for SQL to handle, and sometimes, it just does not matter.

The idea is to understand the way you require to handle data. For each type of requirement, there is a different penalty that you'll have to pay, in order to have what you wish for. There is no magic, no voodoo or anything else, for every solution. There is a penalty at some point, in order to provide you the answer for the requirements you surfaced.

SQL based databases are usually more reliable way to store data, but they are slower in  many ways.

The New types of "NoSQL", are suited for the buzz world of "cloud computing" (aka grid computing), databasebut they return fast with "good" answer, even when something went wrong. The thing you must understand is that they usually queue your request, and handle it later on. It makes you work fast, but you must be less reliable on your data, until you can validate it. It's good when you need to provide multiple requests per seconds, but as you can understand, that's a big price to pay.

The Old style of "SQL", is usually more ACID based. Each action is validated when it executed, and returned to you. It's slower but more reliable with it's answer.

There are in-between databases as well. There are "NoSQL" based databases that are full ACID, and return with the proper answer, and "SQL" databases that are not full ACID and return valid answer that might not be valid when it actually executed.

The thing is, that you must understand and know what, when, and where to choose. The boundaries are not so easy to set on many cases. If you have to provide the user a lot of information, then that's one path to take. But if you have a lot of write and updates, that's another path you should choose

The design of your data, and the way you work, also have effect on how to choose your tool.

So instead of ignoring hypes or joining them, remember, that "Yes SQL" and "No SQL" are two different sides of the same coin. And sometimes you must choose both of them for the same project.

resources

Timeout records – Feature request

Foreword

For several years now, I'm yearning for a feature that I think that all SQL based databases that I know are missing, and throw it back to the program side.

The feature I wish to have is a way to set a specific record to be valid for only a known period of time, and when the time is up, I'll be able to do something.

In this post I'll try to create some sort of general specification for such feature, and I hope that there will be many comments on this that will benefit everyone, and I hopeful, that they will make the idea better.

The Idea

An SQL statement that allow me to create, update and cancel a set of timeout per record or a where statement. It can look like this.

A record that is pointing to such timeout, can not be entered to another timeout rule. Any attempt to add additional timeoutout rule to such record must raise and exception, even if it part of a "where" statement, so the statement will have to have condition to exclude it from the new rules.

A Create new timeout condition can look something like this:

CREATE TIMEOUT <timeout name> FOR <table name> SET <time in seconds | TIMESTAMP timest> <IDENTIFIED BY id | WHERE condition> [ON TIMEOUT TRIGGER <trigger name>]

An Update condtion for existed timeout can look something like this:

UPDATE TIMEOUT <timeout name> FOR <table name> SET <time in seconds | TIMESTAMP timest> <IDENTIFIED BY id | WHERE condition> [ON TIMEOUT TRIGGER <trigger name>]

And a removing of a timeout can look something like this:

DROP TIMEOUT <timeout name>

Looking up for the time left for a record:

SELECT <timeout name [,timeout name ...] | *> FROM <TTL> [where condition]

Where TTL is a place that the query can get this information.

More details

The idea is to be able to raise a trigger when the time is out, but if no trigger was set, then the record or records are removed. If the database have audit-trail (Firebird SQL for example), such trigger-less timeouts will be marked there.

Beside the creation, editing and deletion of the rule, there should be a way to see how much time was left for a specific rule, or set of rules.

If something went wrong, then an exception should be raised.

That's the whole idea in general. I'll be more then happy to hear what you have to say about it.

המפרש החדש שכתבתי ל Redis

בפרק הקודם סיפרתי על הקרב שלי עם Redis. בעקבותיו, שכתבתי את המפרש של Redis לגמרי מהיסוד. יש דברים שהעתקתי מהגרסה הקודמת כי עבדו טוב, אבל שיניתי איך הדברים מתבצעים בפועל גם בקוד הישן.

בכל הנושא הזה, היה לי באג אחד אשר לקח לי יום אחד למצוא אותו, היות והוא התרחש רק במקרים מאוד ספציפיים. בהתחלה חשבתי כי אולי ה mock שאני משתמש בו לא תקין, אז ניסיתי לכתוב אחד בעצמי (במקום הקוד שבמקור לקחתי מwireshark), וגיליתי שהמפרש שלי מצויין אפילו, כי הוא הרים לי מייד חריגה על כך שהמבנה לא תקין (מה שרציתי לבדוק). זו לא חריגה של משהו שלא ניהלתי טוב, אלא זו חריגה אשר התרחשה מהקוד שלי,  אשר נכתב בשביל להעלות במידה ומשהו במבנה לא תקין.

אז התחלתי לשגע את כל העולם ואחותו ברעיונות איך לדבג את הבאג שיש לי, היות ולא הצלחתי למצוא מה הגורם שלו. ובשביל זה צריך בעצם להסביר את הגישה השונה שיצרתי למפרש, ולמה בעצם כל כך קשה לדבג את הקוד. חשוב להדגיש כי הבעיה היא לא לסרוק בתים, אלא להחליט מה שייך למה, מתי ולמה, ולדעת להתאים את עצמך לדרישות. כלומר לרוץ בצורה לינארית משמאל לימין על buffer מעולם לא יצר שום בעיה במימוש (קשור לדיון שהיה לי בנושא), אלא לעשות את זה בצורה קלה, מהירה, ונוחה, זו כבר משימה יותר מורכבת.

אז איך הרעיון של המפרש החדש בנוי, אתם בטח שואלים ? להמשיך לקרוא

האם תכנות בשפות דינאמיות מוריד את יכולות התכנות שלך ?

source code illustrationבזמן האחרון חזרתי לתכנת בצורה ממש רצינית בשפה סטטית, אחרי מספר שנים שאני בעיקר מתכנת בשפות דינאמיות. העניין הוא שמגלה כי יכולות התכנות שלי ירדו פלאים.

אז התחלתי לשאול מספר חברים אשר גם הם מתכנתים כיום בעיקר בשפות דינאמיות, והפלא ופלא, הם מרגישים את אותו הדבר (ולרגע הייתי בטוח שזה רק מדגיש את מה שתמיד היה אצלי ;)).

ללמוד לתכנת בשפת תכנות, זו לא משימה של לימוד תחביר, כי זה הדבר הפשוט והקל ביותר ללימוד, אלא לימוד של חשיבה בהלך הרוח של השפה, כאשר שפה דינאמית שונה בחשיבה שלה משפה סטטית. השוני הזה מגיע בנוסף לדרישות של השפה הספציפית עצמה.

הבעיה היא, שכל שפות סטטיות (אשר אני לפחות מכיר) מכילות הגבלות אשר לרוב אינן קיימות בשפות דינאמיות, ולכן הגישה והחשיבה בעבודה עם שפות סטטיות שונה לגמרי, וכמובן שגם כאן אנחנו מדברים עוד לפני העבודה עם השפה הספציפית עצמה והלך החשיבה שלה. להמשיך לקרוא

המשמעות של בקשת פיטצ'רים לתכנה

כבר כתבתי על הנושא בעבר, אבל אני נדהם כל פעם מחדש הרבה אנשים לא מבינים כמה לא פשוט לפעמים להוסיף תמיכה לפיטצ'ר אפילו הקטן ביותר שיש. לפעמים בקשה ממש "קטנה" כמו שאני ביקשתי, אומרת שכתוב מאוד קשה ומסיבי של הגישה והלוגיקה של הדברים.

זו הסיבה למשל שאני שאלתי את השאלה בצורה ששאלתי. במקום לקבוע שזה דבר הכרחי, פשוט שאלתי בכלל אם זה באמת נחוץ. היות ואינני יודע מה העבודה הנדרשת, ואני יודע שזה nice to have, אבל לא משהו הכרחי באמת. כלומר אפשר לחיות גם בלי זה כמו המצב הנוכחי.

רוב המתכנתים בעצם, ממש לא אוהבים שמבקשים מהם שינוי שאחרי תכנון. רוב המבקשים לא מבינים למה, ויותר חמור, לרוב לא מבינים למה לפעמים אני יכול להגיד שזה יקח עכשיו חודש שלם של פיתוח (כאשר המימוש המקורי לקח שבוע וחצי). העניין הוא שלא רק מדובר בשינוי לוגיקה כלשהי, אלא צריך לשמור על אותה התנהגות שינה כאילו שום דבר השתנה, אבל לחשוב בגישה שונה, מהמימוש המקורי אשר לא מאפשר לי לספק את השינוי. זה גם אומר שצריך לפעמים להתנתק לגמרי ממה שהיה מקודם, ולחשוב ב state of mind אחר, דבר שמאוד קשה כשיש משהו בנוי מולך. אבל במידה ואין לי אפשרות כזו, אז כיצד אפשר לספק את אותה הגישה בעצם ?

גישות כמו Agile, או אפילו market driven נחמדות על הנייר, אבל לא תמיד אפשריות, ולרוב לא באמת ניתן לחשוב על כל גישה עתידית יכולה לצוץ לה פתאום, ולכן גם כאשר כותבים את הקוד הגמיש ביותר ביקום, עדיין יש מקומות לשכתוב בעקבות בקשות, ואז צרך להבין מה באמת חשוב, ומה הוא רק nice to have, והאם ההשקעה הזו באמת טובה וחשובה.

זו הסיבה שלמרות ששיווק וגם מכירות זה דברים חשוב, עדיין למכור ללקוח שהכל אפשרי וניתן לשינוי לפעמים יכול לגרום לך לקרוס לגמרי ולא רק שלא להגיש את המוצר, אלא להתחייב למשהו שטכנולוגית בלתי אפשרי בגישה שאתה נמצא בה עכשיו, ובזמן המהיר ביותר שיוכלו לספק לך את הסחורה.

באג מעניין בFirebird

ביום שישי חברה המספקת שירותים למספר בנקים ומשרדים ממשלתיים ברוסיה, דיווחה על קריסה מאוד מעניינת של Firebird בשרת שלהם.

יש להם שרת בנראה ככה בשעות שנחשבות ל idle:

top - 03:20:39 up 10 days,  8:39,  7 users,  load average: 2.08, 1.87, 2.15
Tasks: 1732 total,   1 running, 1730 sleeping,   1 stopped,   0 zombie
Cpu(s): 11.9%us,  4.0%sy,  0.0%ni, 83.5%id,  0.0%wa,  0.0%hi,  0.6%si,  0.0%st
Mem:  529177288k total, 378587600k used, 150589688k free,   761532k buffers
Swap: 1073741816k total,   130612k used, 1073611204k free, 333281232k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
15840 t-mvv     20   0 33.3g 9.1g  25m S 209.9  1.8 932:23.24 java
15931 root      20   0  578m 226m 165m S 75.3  0.0 286:12.21 rdb_inet_server
16101 root      20   0  486m 198m 164m S 41.4  0.0  60:34.22 rdb_inet_server
15897 root      20   0  956m 509m 166m S 21.5  0.1 126:36.86 rdb_inet_server
46960 qemu      20   0 1365m 1.0g 2156 S  5.2  0.2 973:33.28 qemu-kvm
61680 qemu      20   0 1366m 1.0g 2536 S  4.6  0.2 934:21.36 qemu-kvm
24615 root      20   0  466m 112m  96m S  3.6  0.0   0:08.07 rdb_inet_server
...

[root <at> mvv bin]# ps aux | grep -c rdb_inet_server
719

Database is on a small FusionIO drive:

mount:
/dev/fiob on /mnt/db type ext2 (rw,noatime)

df -h:
/dev/fiob             587G  423G  135G  76% /mnt/db

ls -l:
-rw-rw---- 1 root root 453031493632 Feb 11 03:26 ncore-mvv.fdb

מסתבר שכאשר שרת מסד הנתונים מגיע להגבלה של 2 גיגה לנעילה (הגבלה של מערכת ההפעלה עד כמה שאני מבין) הוא קורס.
עכשיו בשביל להסביר לכם את הנתונים קצת יותר, בשעות ה idle היו כ 2,500 חיבורים פעילים למסד הנתונים שבצעו פעולות.

להמשך קריאה ואולי אף מעקב בעתיד.

Redis סיבוב שלישי

הסיבוב הבא עם Redis הולך להכריע איך יגמר הקרב ביני לבין מסד הנתונים המעצבן הזה.

הצלחתי לגרום למפרש שלי לעבוד עם כל דבר שהפרוטוקול מדבר עליו, ואפילו על מספר דברים שמצאתי שהוא לא מדבר עליו, אבל קיימים. ואז קיבלתי סנוקרת אשר הראתה לי קצת כוכבים. המכה גרמה לי לעצור יומיים ולחשוב איך להתמודד איתה, וב2 בלילה הבנתי מה אני צריך לעשות (ארכימדס, מאחוריך).

הבעיה התחילה כאשר פקודה (slowlog) אשר נוצרה לפני 7-8 חודשים במסד נתונים מחזירה משהו אשר מנוגד לגמרי לכללי הפרוטוקול של המסד. כלומר היא מחזירה ערך במבנה חוקי, אבל הפרוטוקול אינו מדבר על הדרך הזו שבכלל נתמכת. ואז בתעוד הפקודה עצמה (לא של הפרוטוקול) אני מוצא משפט קטן ומעצבן שנכתב על השימוש בתכנת ה cli של המסד עצמו: להמשיך לקרוא

מיקום גיאוגרפי בעולם אלקטרוני

locationאחת הצרות שהגיעו לנו עם ביאת הסלולר לעולם האינטרנט, היא שיותר ויותר יש לנו שירותים מבוססי מיקום. אממה, הם גם שירותים שמתיימרים לתת תוכן "מקומי" כלשהו. אבל נגיד וקוראים לי ריצ'רד, ואני מבקר בישראל מהאי הבריטי – אנגליה. אני אתחיל לקבל מידע בעברית, ואולי אף בערבית, למרות שהשפה אותה אני דובר היא אנגלית.

יותר מזה, תוכן שנגיש לריצ'רד באי מגוריו – אנגליה, ובכן הרבה ממנו לא זמין עבורו בישראל. אבל ריצ'ארד משלם אגרת טלויזיה באנגליה, ונאמן להוד מלכותה, ופתאום מקבל עונש על כך שבחר להתנתק מהאי למסע עסקים באיזה חברת הזנק נידחת במחוז שנקרא מדינת ישראל.

התניית שירותים והתנהגות גאוגרפיים מכילה הרבה יתרונות כמובן, שלא תבינו את זה לא נכון, אבל יש בה בעיקר שימוש שגוי לגמרי ממה שצריך שיהיה. בישראל למשל לכתובת IP אין באמת חשיבות למיקום שלך. היות ומרבית ספקיות האינטרנט יושבות באיזור אחד הנמצא בעיר לא קיימת ברחוב אשר קיבל את שמו לאור מה שנמצא מתחתיו – סיבים.

יש גם חברה נוספת אשר יושבת בעיקר בחיפה, והיא התמזגה עם עוד חברה שישבה בראש העין. כך שזיהוי המיקום לפי כתובת הגלישה אינה מדוייקת. יותר מזה, מה אם אני משתמש בשירות VPN. נגיד ואני גולש באמצעות חיבור VPN של חברה מסויימת ומקבל ממנה את ההתקשרות לרשת האינטרנט. האם אז אתם יודעים מה המיקום שלי ?

אז הפתרון הוא "כמובן" geolocation. לקחת ממכשיר מבוסס רשת סלולרית או מתוך מכשיר מבוסס מיקום כדוגמת GPS את המיקום שלנו, ולהגיד שאנחנו "כאן" ולתקוע במפה עוד נעץ חסר תועלת. אממה, מה קורה כאשר המידע שגוי (בכוונה או לא) ?

למשל כאשר אני מועיל בטובי להשתמש בשירותי Identica, ובכן בגלל שאינני מוכן למסור את המיקום שלי, אני תמיד מופיע כאילו אני נמצא בצרפת. אבל מעולם לא הייתי במדינה הזו. הייתי במדינות באיזור שלהם, אבל לא אצלה.

כאשר אתם בונים שירותים, אנא ממכם, אל תיצרו את השירות רק לפי מיקום, אפשרו לי – המשתמש לבחור טוב יותר מה אני רוצה לקבל ואיך.

תודה !