Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Dwie kopie skryptu naraz dobierają się do tego samego rekordu bazy danych, Jak temu zaradzić
L_Devil
post 29.05.2007, 20:44:45
Post #1





Grupa: Zarejestrowani
Postów: 195
Pomógł: 0
Dołączył: 13.04.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Witam!

Problem mam z moim serwisem bazującym na php 5 i mysql 4.1
Otóż mój skrypt musi co jakiś odcinek czasu (zwykle godzinę) zaktualizować pewne dane w bazie danych. Dotychczas robiłem to, sprawdzając przy każdych odwiedzinach, czy minęła już data aktualizacji, po czym zapisywał ową datę w bazie danych. Administrator serwera nie udostępnia mi Crona, tym niemniej to rozwiązanie działało... do niedawna. Niestety, niedawno mój serwis zyskał na popularności i zdarza się, że dwie kopie skryptu są uruchamiane niemal jednocześnie. Jak sprawić, by tylko jedna mogła zaktualizować bazę danych? Słyszałem coś o blokowaniu tabel, jak to zrobić i czy może pomóc w tym konkretnym przypadku?

Pozdrawiam


--------------------
Językiem którym najlepiej operują wszyscy programiści są przekleństwa.
Go to the top of the page
+Quote Post
Mazur_pl
post 29.05.2007, 21:08:53
Post #2





Grupa: Zarejestrowani
Postów: 87
Pomógł: 0
Dołączył: 11.05.2007

Ostrzeżenie: (0%)
-----


Możesz zrobić to tak:
Kiedy ktoś lub coś robi z bazą danych zapisuj jego session_id() w bazie .
Kiedy wejdzie druga osoba sprawdzasz czy jakiś wpis jest już w bazie danych. Jeżeli tak to blokujesz dostęp jeżeli nie to dopuszczasz . Potem przy wyjściu usuwasz wpis z bazy danych.

(To moja propozycja) .
Go to the top of the page
+Quote Post
dr_bonzo
post 29.05.2007, 21:30:23
Post #3





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


TRANSAKCJE (kropka)


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
cicik
post 29.05.2007, 21:44:09
Post #4





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(Mazur_pl @ 29.05.2007, 22:08:53 ) *
Możesz zrobić to tak:
Kiedy ktoś lub coś robi z bazą danych zapisuj jego session_id() w bazie .
Kiedy wejdzie druga osoba sprawdzasz czy jakiś wpis jest już w bazie danych. Jeżeli tak to blokujesz dostęp jeżeli nie to dopuszczasz . Potem przy wyjściu usuwasz wpis z bazy danych.

(To moja propozycja) .


Wszelkie tego typu pomysły są ZŁE. We wszystkich tego typu pomysłach da się znaleźć taki scenariusz równoległego wykonania dwóch zapytań kiedy owy sposób nie zadziała.
Dlaczego? Dlatego, że w takich przypadkach operacje sprawdzenia czy jest nałożona blokada i nałożenia blokady są PRZERYWALNE co oznacza, że pomiędzy nie może sie wepchać inne żądanie.
Jedynym sposobem, tak jak kolega wyżej napisał, są TRANSAKCJE.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
L_Devil
post 30.05.2007, 18:19:16
Post #5





Grupa: Zarejestrowani
Postów: 195
Pomógł: 0
Dołączył: 13.04.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Dzięki, już googlam o Transakcjach mySql winksmiley.jpg


--------------------
Językiem którym najlepiej operują wszyscy programiści są przekleństwa.
Go to the top of the page
+Quote Post
1010
post 30.05.2007, 18:51:44
Post #6





Grupa: Zarejestrowani
Postów: 749
Pomógł: 37
Dołączył: 3.10.2006

Ostrzeżenie: (0%)
-----


Gdzieś kiedyś słyszałem że mysql ma wbudowaną taką blokadę w przeciwieństwie do sql.... Może się mylę


--------------------
Go to the top of the page
+Quote Post
L_Devil
post 30.05.2007, 19:38:16
Post #7





Grupa: Zarejestrowani
Postów: 195
Pomógł: 0
Dołączył: 13.04.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Oki, przegrzebałem dokumentację, ale mam problem jak to ładnie połączyć w całość:

robię tak:

  1. START TRANSACTION;
  2. SELECT value FROM config WHERE name='lasttime' LOCK IN SHARE MODE;
  3. -- Kod php sprawdza value i ocenia czy należy już dokonać aktualki. Jeżeli tak:
  4. -- Różne operacje
  5. UPDATE config SET value=value+3600 WHERE name='lasttime';
  6. COMMIT;
W tym problem, że zapytanie z Selectem wykona się bez względu na lock w każdej sesji - a więc może zajść sytuacja:
+jeden skrypt dostaje polecenie select i otrzymuje informacje, że już czas na aktualke
+druga kopia skryptu otrzymuje te same dane, nim pierwsza zdąży zaktualizować pole. Rozpoczyna swoją aktualizację, która jest wpisana w następną transakcje
+obie transakcje zostają wykonane jedna po drugiej - a więc błędnie

Jak sobie z tym poradzić? Co przeoczyłem? Zaznaczam, że korzystam z wersji mySQL 4.1 winksmiley.jpg

Ten post edytował L_Devil 30.05.2007, 19:41:01


--------------------
Językiem którym najlepiej operują wszyscy programiści są przekleństwa.
Go to the top of the page
+Quote Post
cicik
post 31.05.2007, 07:12:26
Post #8





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Jest taka składnia w sqlu SELECT ... FOR UPDATE.
Dla mysqla można poczytać o tym tutaj: http://dev.mysql.com/doc/refman/5.0/en/inn...king-reads.html

Edit:
Właśnie zauważyłem, że korzystasz z mysql 4.1. Nie wiem czy na tym da się zrobić cokolwiek.

Ten post edytował cicik 31.05.2007, 07:13:32


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
L_Devil
post 31.05.2007, 12:48:34
Post #9





Grupa: Zarejestrowani
Postów: 195
Pomógł: 0
Dołączył: 13.04.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


MySQL 4.1

Wygląda na to, że jest... Czyli poprawne będzie zrobienie tego tak:
  1. START TRANSACTION;
  2. SELECT value FROM config WHERE name='lasttime' FOR UPDATE;
  3. -- Kod php sprawdza value i ocenia czy należy już dokonać aktualki. Jeżeli tak:
  4. -- Różne operacje
  5. UPDATE config SET value=value+3600 WHERE name='lasttime';
  6. COMMIT;

Gdyby druga kopia skryptu uruchomiła się w tej samej chwili, to z Selectem będzie musiała zaczekać? Tak? (Pytam bo nie wiem, a nie chcę popełnić błędu winksmiley.jpg )


--------------------
Językiem którym najlepiej operują wszyscy programiści są przekleństwa.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 25.07.2025 - 09:50