2012-12-18 11 views
5

Wiem, że to pytanie było już wcześniej zadawane, ale nadal jestem zdezorientowany i chciałbym uniknąć problemów, zanim przejdę do programowania, jeśli to możliwe.Jak właściwie unikać warunków wyścigu Mysql

Mam plan wewnętrznej witryny z co najmniej 100 użytkownikami aktywnymi w danym momencie. Użytkownicy wysłaliby element (wstawiony do db z 0 jako jego wartością), a ten element byłby wyświetlany przez stronę php (zapytanie db). Użytkownicy mają wtedy możliwość naciśnięcia przycisku i zablokowania tego elementu jako swojego (przypisanie wartości tego elementu jako jego identyfikatora)

Jak zapewnić, że 2 lub więcej użytkowników nie będzie pobierać tego samego produktu w tym samym czasie? . Wiem, że w programowaniu takim jak C++ po prostu użyłbym zwykłego ol mutex lock. Czy jest ich odpowiednikiem w mysql, gdzie zablokuje tylko jeden wpis pozycji? Widziałem odniesienia do LOCK_TABLES i GET_LOCK i wielu innych, więc nadal jestem bardzo zdezorientowany, co jest najlepsze.

Wiele osób może ścigać się, naciskając jeden przycisk, co może być katastrofalne, gdy wiele osób otrzyma potwierdzenie.

Wiem, że to doskonały przykład wyścigu, ale dla mnie mysql to obce terytorium.

Oczywiście zapytam o wartość przedmiotu, zanim go zaktualizuję i upewnię się, że nie został napisany, ale jaki jest najlepszy sposób, aby uniknąć tego stanu wyścigu.

Z góry dziękuję.

Odpowiedz

2

Aby to osiągnąć, musisz jakoś zablokować nagranie. Dodaj kolumnę LockedBy dotrzymującemu 0.

Gdy ktoś naciska przycisk wykonać zapytanie przypominający ten:

UPDATE tabela SET LockedBy = gdzie LockedBy = 0 i id =;

Po aktualizacji należy sprawdzić poprawność wierszy (w php mysql_affected_rows). Jeśli wartość wynosi 0, oznacza to, że zapytanie nie zaktualizowało niczego, ponieważ kolumna LockedBy nie ma wartości 0 i dlatego jest blokowana przez kogoś innego.

Nadzieja to pomaga

+0

Po co tworzyć zupełnie nową kolumnę? czy nie możesz użyć tej samej taktyki w istniejącej kolumnie? –

2

Gdy piszesz wiersz, ustaw kolumnę NULL, a nie 0.

Następnie, gdy użytkownik aktualizuje wiersz, aby to ich własne, zaktualizuj go w następujący sposób:

UPDATE MyTable SET ownership = COALESCE(ownership, $my_user_id) WHERE id = ... 

COALESCE() zwraca pierwszy niezerowy argument. Więc nawet jeśli ty i ja aktualizujemy się równolegle, pierwszy, który zatwierdza, ustawia wartość. Drugi nie zastąpi tej wartości.

0

Można rozważyć Transakcje

BEGING TRANSACTION; 
SELECT ownership FROM ....; 
UPDATE table .....; // set the ownership if the table not owned yet 
COMMIT; 

a także można ROLLBACK wszystkie zapytania od transakcji, jeśli złapany błąd!

Powiązane problemy