Cachuje w pamieci wyniki zapytań, tj jesli raz odczytam jakis wiersz to trzymam go w pamieci az do konca wykonywania skryptu, i w razie czego z niego korzystam.
Sytuacja modelowa:
Dwóch uzytkownikow poprzez skrypt WWW probują zmodyfikować rekord x w tabeli bazy danych.
zalozmy ze w rekord x mozna wpisac jakas wartosc liczbową lub flagę _dont_modify jesli cos tam sie zakonczylo i juz nie powinnismy modyfikowac tego.
0. rekord x = 10.
1. Uzytkownik 1 odczytuje rekord x
2. uzytkownik 2 odczytuje rekord x
3. Uzytkownik 2 robi update obiekty x. Sprawdza (korzystajac z wartosci cache) czy (x != _dont_modify). Jest to prawda wiec moze edytowac: wpisuje flage _dont_modify
4. Skrypt 2 konczy swoje dzialanie
5. Uzytkownik 1 robi update obiektu x. Sprawdza (korzystajac z wartosci cache) czy (x!= _dont_modify). Jest to prawda (w cache jest stara wartosc nadal) wiec wpisuje wartosc np. 15.
6. Skrypt 1 konczy swoje działanie.
Efekt?
Uzytkownik zakonczyl np. swoja bitwe i zostal wpisany status _dont_modify. Jednoczesnie drugi uzytkownik podawal inny wynik ktory byl sprzeczny,
i bitwa nie zostala zakonczona wg niego. Efekt jest taki ze mamy wyniki w drzewie, bitwa zostala uznana za zakonczoną, w dalszej czesci programu zmodyfikowane zostalo drzewo przechowujace turniej i utworzone kolejne bitwy miedzy graczami, a bitwa w dalszym ciagu ma nieustalony wynik! (przyjmuje ze bitwa jest zakonczona gdy jest ustawione dont_modify).
Jak to rozwiazac? Transakcje? Ale to wtedy caly odczyt i zapis musialby byc w jednej transakcji... padnie mi wydajnosc na stronie.
I drugie pytanie, jak podobny problem rozwiazac w cache opartym na plikach?
Co do plikow myslalem nad rozwiazaniem ktore odczytuje plik przed samym zapisem i porownuje czy rekord ktory chcemy update'owac nie zmienil sie, i jesli sie zmienil to wyrzuci wyjatek ale to tez nie zalatwia sprawy, poniewaz jesli mam proces ktory jesli cos zajdzie to najpierw
zapisuje wartosc do tabeli X a pozniej do pliku Y, i plik Y wyrzuci wyjatek i nic nie zapisze, a sterowanie i rozpoznawanie stanu tego obiektu opiera sie na wartosci Y, to mam nowa wartosc i stary stan co rowniez moze doprowadzic do szalonych bzdur.
Niby moge zrobic flock(LOCK_EX) na ten plik cache, ale wtedy blokuje kazde kolejne wywolanie skryptu na 100ms, a updaty nie beda az tak czesto.
Ogolnie to chce miec klase abstrakcji dostepu do zrodla danych ktore bedzie udostepnialo taki sam interfejs zarowno przy zapisie do plikow obiektow bazy danych jak rowniez do bazy danych (niektore rzeczy lepiej w plikach a niektore lepiej w DB).
Poradzilem sobie zakładając locka LOCK_EX wtedy kiedy wiem ze bede cos zapisywal, a zakladam LOCK_SH jak tylko odczytuje i wyswietlam, mimo wszystko moze ktos zna lepsze rozwiazanie?