כמה INSERT בדיוק באותו רגע - wp
-
@WWW
כתבתי בנושא wp
כלומר wordpress
mysqli@WWW אמר בכמה INSERT בדיוק באותו רגע - wp:
בעקרון זה התפקיד של מנוע מסד הנתונים.
אם זה היה רק הכנסת שורה הייתי מאמין שהמסד אכן לא יתן.
אבל מה שקורה כאן זה משיכת נתונים ולאחר מכן ע"פ התניות שהקוד יעשה, אני מכניס שורה חדשה.
אם שני האנשים ימשכו ביחד את הנתונים אז שניהם יקבלו את אותו המקום... -
@ש-ב-ח אמר בכמה INSERT בדיוק באותו רגע - wp:
mysqli
זה לא כתבת.
@ש-ב-ח אמר בכמה INSERT בדיוק באותו רגע - wp:
אם זה היה רק הכנסת שורה הייתי מאמין שהמסד אכן לא יתן.
אבל מה שקורה כאן זה משיכת נתונים ולאחר מכן ע"פ התניות שהקוד יעשה, אני מכניס שורה חדשה.
אם שני האנשים ימשכו ביחד את הנתונים אז שניהם יקבלו את אותו המקום...@dovid כתב לאחרונה בפורום שיש פונקציה מיוחדת ב SQL שיבצע פעולה רק אם הפעולה האחרת התבצעה, לא זוכר איך קוראים לזה.
אני היה לי סיפור דומה לפני תקופה קצרה שגרם לי לשגיאות חמורות, וסידרתי את זה בקלות.
היה לי שאילתא במסד נתונים שמחזירה שורה ראשונה בטבלה שהיא בסטטוס 1, והיה מחזיר ללקוח ערך מסוים מהשורה הזאת, ובהמשך משנה את הסטטוס ל 2.הבעיה היתה שקרה ו2 ניגשו ביחד וקיבלו אותו שורה, ואז שניהם קיבלו אותו ערך...
מה שעשיתי זה בשעת עדכון הסטטוס שוב פעם סינון שישנה רק אם הסטטוס כרגע 1, ואם לא שלא ישנה כלום, ואז הייתי מחזיר שגיאה.
מקווה שהובנתי...
-
@ש-ב-ח הבעיה היא לא הSQL
הבעיה היא הPHP, שמה בהחלט יכול להיות בעיה של ריצה בו זמנית.
הפתרון לזה הוא נעילה, הקטע שחייב לרוץ "לבד" אתה עוטף עם flock.למשל אם יש לך קוד ששורה א' שלו בודקת אם המקום הנבחר פנוי, ב. אם התשובה חיובית מכניסה INSERT למסד, נכנס גולש מס' 1 ומתבצע עבורו שורה א, והתשובה חיובית. לבינתיים יש גולש 2 שגם עבורו מתבצעת שורה א', וגם שמה השורה חיובית. כעת שורה ב' תתבצע עבור שני הגולשים.
אם שני השורות הללו יהיו בבלוק נעול, אז גולש 2 לא ייכנס לשורה א' עד שגולש 1 יגמור את שורה ב'.למה אני כותב שהבעיה בPHP? כי אם תגלגל את האחריות על המסד נתונים, למשל תעשה שהשדה של מס' המקום הוא ייחודי (אסור כפילות), אז ה"דאגה" של הבו זמניות ירדה מכתפיך - המסד נתונים מבצע את הנעילה וממילא מחזיר שגיאה לאחד מהם (מה אכפת לך איזה). אתה בקוד תופס את השגיאה (או לא..) עם catch וכותב למשתמש "אויש, המקום כבר נתפס לבינתיים".
-
את המתכוון לכזה דבר
<?php class Locker { public $filename; private $_lock; public function __construct($filename) { $this->filename = $filename; } /** * locks relevant file */ public function lock() { touch($this->filename); $this->_lock = fopen($this->filename, 'r'); flock($this->_lock, LOCK_EX); } /** * unlock above file */ public function unlock() { flock($this->_lock, LOCK_UN); } } $locker = new Locker('locker.lock'); echo "Waiting\n"; $locker->lock(); echo "Sleeping\n"; sleep(30); echo "Done\n"; $locker->unlock(); ?>