נעילה לוגית ב Web

רץ ברשת

New member
נעילה לוגית ב Web

WebPage באפליקציה דוט נטית, מציגה Grid עם נתונים, משתמשים רבים רואים את ה Grid הנ"ל, וכל משתמש יכול ללחוץ על רשומה בגריד, ובעצם לנעול אותה לשימושו (עד אשר ישחרר). כאשר משתמש לוחץ על רשומה, מתעדכן ב DB שדה אינדיקציה המעיד על כך שהרשומה ננעלה (וגם מתועד מי נעל), וכאשר הגולש משחרר את הרשומה, האינדיקציה נמחקת (וגם מי נועל). הנ"ל עובד יפה, פרט למקר קצה שבו יש בעצם תחרות בין 2 משתמשים (או יותר), ובשל בעיית סנכרון זמנים, כאשר הם מנסים לנעול את אותה רשומה, לעיתים שניהם "מצליחים" (בפועל ב DB מעודכן שרק אחד נועל, אבל גם השני קיבל את המסך שמעיד על הצלחה בנעילה). הנ"ל קורה מכיוון ששניהם שולפים את אינדיקציית ה "נעול" מה DB באותו שבריר שנייה, ושניהם מקבלים "לא נעול".
כיצד ניתן להתגבר על בעיה זו ? חשבתי להוסיף השהייה זמן רנדומלי לפני ביצע הנעילה, אך הרי גם במצב זה יתכן ש 2 גולשים יקבלו את אותו הזמן, ושוב יגיעו לבסיס הנתונים באותו שבריר שנייה...
 

arnonrgo

New member
טרנזקציה

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

רץ ברשת

New member
תגובה :

לא מדובר על Lock ברמת ה DB, אלא על עדכון שדה בטבלה ל "1" המייצג רשומה נעולה לוגית, ו "0" לשחרור. 1. לא הבנתי איך טרנזקציה יכולה לפתור את הנושא, הרי 2 משתמשים יכולים לפתוח טרנזקציה באותו הרגע, ושניהם יראו את הרשומה כלא נעולה... 2. לגבי שחרור הנעילות - נקודה טובה, השחרור בעייתי כאשר המשתמש סוגר את הדפדפן (בעזרת ה X למשל)...
 

arnonrgo

New member
תשובה

אני מבין שלא מדובר על lock ברמת הDB אבל כדי לבצע את הlock הלוגי כדאי לבצע את הפעולות שכתבתי (בדיקת הסטאטוס, שינוי הסטאטוס) בתוך טרנזקציה פסימיסטית אחת. במצב כזה הDB מבטיח שרק אחד יקבל lock על הרשומה - הטרנזקציה השניה לא תצליח לקבל lock ולכן לא תתבצע אם יתבצע retry בפעם הבאה כבר הסטאוס יהי מעודכן לנעול לוגי המשמעות של טרנזקציה היא 4 דברים שידועים תחת ראשי התיבות ACID Atomic - כל הפעולות בטרנזקציה מתבצעות (או לא ) ביחד Consistent - הDB נשאר במצב נכון בין אם הטרנזקציה הצליחה או לא Isolated - בזמן ביצוע הטרנזקציה גורמים אחרים לא רואים את מצבי הביניים Durable - השינויים נשמרים כדי להבטיח את הACIDness - ובמיוחד הconsistency הDB משתמש בנעילות תחשוב שבמקום קריאה וכתיבה היית צריך לכתוב לשני שדות הקשורים בינהם (זו בעיה שקולה) אם בזמן שאתה כותב לשדה אחד מישהו אחר יכול לכתוב לשדה השני יש לך בעיה של נכונות. במקרה שלך אתה צריך להבטיח שהlock על הרשומה קיים עוד לפני הקריאה (בדיקת הסטאטוס)- כדי להבטיח שאף טרנזציה אחרת לא תוכל לבצע קריאה כזו בזמן שאתה מעדכן את הסטאטוס אני מכווה שזה לא יבלבל אותך אבל דבר דומה שאולי אתה מכיר ואתה יכול לחשוב עליו זה ההתנהגות של critical section במקרה של . threading
 

רץ ברשת

New member
../images/Emo51.gif רבה על ההסבר הנרחב, כלומר

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

ייוניי

New member
אני לא בטוח שזה מספיק

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

arnonrgo

New member
זה בדיוק מה שאמרתי

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

רץ ברשת

New member
חשבתי ש...

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

arnonrgo

New member
בגדול אתה כן צריך טרנזקציה

אתה צריך שהselect והupdate ירוצו באותה טרנזקציה אחרת בין הקריאה לכתיבה ישתחרר ה lock - מ מה שכן - אם אני חושב על זה , אתה לא באמת צריך יותר מצעד אחד
Update LockTable set lockFlag=someuserid Where lockFlag=unlocked value​
רק אחד הupdate-ים יצליח מפני שהSQL בעצם מריץ כל שורה בתוך טרנזקציה באופן explicit (וזו גם הסיבה בפתרון של קריאה לחוד וכתיבה לחוד ש שהlock ישתחרר אם לא תגיד לSQL ששתי הפעולות רצות בתוך אותה טרנזקציה)
 
למעלה