![]() |
![]() ![]() |
![]() |
![]() ![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Cześć,
stworzyłem stronę z konkursami online, jest oparta o chat, w którym użytkownicy wpisują odpowiedzi. Jeżeli trafią jedną z trzech opcji, użytkownik wygrywa. W takiej sytuacji do tabeli z wiadomościami była dodawania nowa, a później wykonywał się UPDATE w tabeli z konkursami, żeby ustawić zwycięzcę, jeżeli odpowiedź jest prawidłowa. Niestety, ostatnio są problemy - skrypt dwa razy dodał prawidłową odpowiedź do chatu, ale nie ustawił zwycięzcy i wygrała osoba, która podała odpowiedź jako trzecia. Niestety kto inny zajmuje się administracją - nie mogę założyć dodatkowych logów itp. Zastanawiam się, jak zabezpieczyć skrypt przed taką sytuacją. Korzystam z mysqli, obydwie tabele na silniku InnoDB. Uwarunkowałem dodanie wiadomości do chatu od tego, czy wykonano UPDATE, ale obawiam się, że to za mało. Poniżej fragment pliku odbierającego ajaxowe zapytania:
Czy ktoś mógłby podać jakąś wskazówkę co jeszcze można zrobić? |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
1. Wszelkie dane modyfikujące stan bazy danych powinny być objęte jawną transakcją.
2. W tej chwili IF sprawdzający czy zmodyfikowano dane odnosi się wyłącznie do $json['won'] = ... - zapytanie INSERT wykona się właściwie zawsze. |
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Tak, wiadomość ma się wysyłać za każdym razem, bo to chat
![]() Wcześniej wyglądało to w taki sposób (wyciąłem treści zapytań, są takie same):
Problem był, taki, że jeżeli wiadomość była odpowiedzią, to dodawała się do tabeli z wiadomościamu z chatu, ale nie aktualizowała kolumny contests.winner. Efekt był taki, że podano poprawną odpowiedź, która nie wygrywała konkursu. Nie znam się za bardzo na transakcjach, ale z tego, co mi wiadomo, transakcja korzysta z tabeli w takim stanie, w jakim była w momencie rozpoczęcia transakcji. Czyli w sytuacji kiedy w minimalnych odstępach czasu przychodzą dwa wpisy z wygrywającą odpowiedzią, to wygra ten późniejszy, bo w momencie rozpoczęcia transakcji konkurs nie był jeszcze wygrany. Ten post edytował Kikert 18.07.2012, 11:34:40 |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Wielkie dzięki, zaraz zobaczę, jak to śmiga
![]() Jeszcze drobne pytanie - co stanie się w sytuacji, kiedy ktoś inny też będzie wykonywał kod w tym samym czasie? Czy jego żądanie zostanie po prostu zignorowane, czy wykonane z opóźnieniem? Ten post edytował Kikert 18.07.2012, 12:52:39 |
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
W przypadku gdy na tabelę jest założona blokada inne zapytania będą musiał poczekać ze swoim wykonaniem do czasu zdjęcia tej blokady, czyli wykonają się z opóźnieniem.
Swoją drogą, jeżeli w mechanizmie sprawdzania czy dany wpis jest zwycięski korzystasz z zapytania UPDATE oraz affectedRows możesz nawet zrezygnować z blokady odczytu tabeli. |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 3.08.2025 - 21:01 |