Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Blokowanie tabel w bazie jako zabezpieczanie przed usunięciem usuniętych danych (?)
Forum PHP.pl > Forum > PHP
Jarod
Witam,

nie wiem jak ugryźć pewien problem, tzn wiem jak mogę sobie z nim poradzić ale nie jestem pewny czy nie ma lepszych i sprawdzonych sposobów, dlatego będę wdzięczny za wszelkie opinie i wskazówki. Poniżej opiszę dwa problemy. Z pierwszym niedługo się zmierzę a drugi muszę rozwiązać.

Problem 1: Wyobraźcie sobie, że piszecie aplikację, która będzie służyć do układania grafików dla pracowników (to tylko przykład). Kierownicy poszczególnych działów i inne osoby do tego wyznaczone (nie jest to jedna osoba) mogą układać i edytować grafiki.

Osoba A wybiera pewnego pracownika, któremu edytuje grafik na miesiąc marzec. Po kliknięciu na link zawierający jego imię i nazwisko, wchodzi w tryb edycji grafiku tej osoby. Widzi cały miesiąc i może dokonywać zmian godzinowych dla poszczególnych dni, a po dokonaniu zmian, naciska przycisk "weryfikuj". Sprawdzane są warunki i jeśli wszystko jest ok, może zapisać zmiany. Jeśli nie są spełnione pewne zalezności, wyświetlany jest odpowiedni komunikat. Pomimo błędów osoba ta i tak może świadomie zapisać taki "błędny" grafik.

Edycja takiego grafiku czy samo dodawanie nowego dla pracownika zajmuje trochę czasu. Problemem jest to, że druga osoba może chcieć w tym samym czasie edytować lub dodać grafik dla tej samej osoby. Może się trochę zdenerwować, jeśli okaże się, że układała grafik 20minut i podczas próby zapisania do bazy otrzyma komunikat, że grafik już istnieje (osoba B już go dodała) i można go tylko edytować.

Pomyślałem, że dobrze byłoby blokować tabele a konkretnie użytkowników, którzy są w danym momencie dodawani albo edytowani. Ale samo blokowanie raczej nie spełni moich oczekiwań. Dlaczego? Nie jestem pewny (muszę to sprawdzić ale teraz nie mam chwilowo dostępu do bazy) ale czy z blokowaniem tabel nie jest tak, że jak skrypt php kończy się wykonywać to blokady są zdejmowane?
Jeśli tak nie jest, tylko można z poziomu php ustawić blokady w bazie do odwołania, to co będzie jeśli użytkownik zamknie przeglądarkę podczas edycji i pójdzie sobie gdzieś? Nikt nie może edytować ani dodać takiego pracownika, ponieważ teoretycznie jest on edytowany/dodawany przez inną osobę..

Jak sobie poradzić z tym problemem?



Problem 2:
Załóżmy że w bazie istnieją jakieś produkty. Możemy z poziomu aplikacji php dodawać nowe, edytować je i usuwać. Usuwanie odbywa się w następujący sposób:
- wybieramy opcję usuń produkt
- z listy rozwijanej wybieramy nazwę produktu i klikamy usuń (za pomocą $_POST przesyłamy sobie id produktu do usunięcia).

Osoba A wybiera z listy rozwijanej produkt do usunięcia ale nie naciska przycisku usuń, bo... np zadzwonił telefon:)
W między czasie osoba B usunęła ten produkt. Osoba A skończyła rozmawiać i naciska przycisk "usuń". I... łapiemy wyjątek SQL...
Ja uważam (i tak przyjąłem pisząc aplikację), że wyjątek krytyczny (myślę tu o wyjątkach sql) to coś co powinno przerwać pracę aplikacji.

Problem ten mógłbym rozwiązać poprzez sprawdzanie (przed samym zapytaniem usuwającym produkt) czy ten produkt istnieje nadal. Ale... może się zdarzyć (mało prawdopodobieństwo ale jest to możliwe a muszę to uwzględnić), że od sprawdzenia czy produkt istnieje a do jego usunięcia, ktoś ten produkt zdąży usunąć. I znowu mamy wyjątek SQL.

Macie jakieś pomysły?


Pozdrawiam
dr_bonzo
2.
Cytat
Ale... może się zdarzyć (mało prawdopodobieństwo ale jest to możliwe a muszę to uwzględnić), że od sprawdzenia czy produkt istnieje a do jego usunięcia, ktoś ten produkt zdąży usunąć. I znowu mamy wyjątek SQL.
- jesli chodzi o 1 request php, no to masz do tego transakcje (masz pewnosc ze nikt ci bazy nie zmieni od selecta do delete).

No a jesli rozdzielasz na 2 ekrany - to po prostu wyswietlasz error ze rekord nie istnieje (bo nie istnieje), lub ktos go w miedzyczasie usunal (wersja bardziej user friendly - user wie czemu sie to stalo)

1. Osoba rozpoczynajaca tworzenie grafiku, ustawia dla tego usera, na dan miesiac itd, znacznik ze edycja grafiku jest zablokowana (wiec inny user nie bedzie mogl od tego momentu zaczac tworzyc nowego grafiku - dostanie error ze rekord zablokowany).

Blokade zwalniasz jak user skonczy edytowac grafik, lub np. po godzinie (jesli telefon zadzwonil, a user nie skonczyl grafika)
Jarod
Cytat(dr_bonzo @ 15.02.2008, 00:04:13 ) *
2.
- jesli chodzi o 1 request php, no to masz do tego transakcje (masz pewnosc ze nikt ci bazy nie zmieni od selecta do delete).

No a jesli rozdzielasz na 2 ekrany - to po prostu wyswietlasz error ze rekord nie istnieje (bo nie istnieje), lub ktos go w miedzyczasie usunal (wersja bardziej user friendly - user wie czemu sie to stalo)

Tak czy inaczej i tak stosuję transakcje ponieważ operacja usuwania wykonywana jest na 3 tabelach (muszę zachować spójność bazy).
Najpierw wybiera z listy i klika przycisk usuń, kontroler przejmuje żądanie i sprawdza czy zostały przesłane dane za pomocą $_POST - tak kieruje do modelu, który w transakcji usuwa dane.
Więc więcej niż 1 request. W takim razie tuż przed odpaleniem transakcji musiałbym sprawdzić czy dany produkt istnieje.

if (rekord_istnieje()) odpalamy_transakcje();
else błąd().

Załóżmy, że baza się przymuliła na chwilę, albo inny user wstrzelił się z usuwaniem tego samego produktu (przyznaj jest to prawdopodobne) pomiędzy
rekord_istnieje() a odpalamy_transakcje()... Wyjątek SQL..

Cytat(dr_bonzo @ 15.02.2008, 00:04:13 ) *
1. Osoba rozpoczynajaca tworzenie grafiku, ustawia dla tego usera, na dan miesiac itd, znacznik ze edycja grafiku jest zablokowana (wiec inny user nie bedzie mogl od tego momentu zaczac tworzyc nowego grafiku - dostanie error ze rekord zablokowany).

Blokade zwalniasz jak user skonczy edytowac grafik, lub np. po godzinie (jesli telefon zadzwonil, a user nie skonczyl grafika)

Ok, a jeśli użytkownik A cały czas pracuje nad grafikiem dla Jasia Kowalskiego i potrzebuje więcej czasu niż godzinę? Po godzinie blokada jest ściągana (pomimo tego że on nadal pracuje), w między czasie użytkownik B dodaje grafik dla Jasia. Użytkownik A podczas próby dodania dostaje wyjątek SQL..

Problem dotyczy także edycji. Cały proces będzie skomplikowany. Np istnieje konieczność zmian w grafiku. Osoba A dokonuje ich bardzo powoli, mija godzina, rekord zostaje odblokowany, osoba B zniecierpliwiona opieszałością osoby A dokonuje szybkiej edycji i zapisuje. W tym samym czasie osoba A zapisuje swoją edycję (inny układ godzin) i osoba B jest wkurzona bo system pokazuje inne godziny niż ona zapisała..
nevt
Co do problemu nr 2 - ten problem istnieje tylko w twojej wyobraźni - jeśli wyślesz do bazy polecenie DELETE dla nieistniejącego rekordu to nic się nie stanie - nie wystąpi żaden wyjątek ani błąd SQL - to tak samo jak SELECT który zwraca pusty wynik dla niespełnionego warunku w WHERE...
Jarod
Cytat(nevt @ 15.02.2008, 07:26:32 ) *
Co do problemu nr 2 - ten problem istnieje tylko w twojej wyobraźni - jeśli wyślesz do bazy polecenie DELETE dla nieistniejącego rekordu to nic się nie stanie - nie wystąpi żaden wyjątek ani błąd SQL - to tak samo jak SELECT który zwraca pusty wynik dla niespełnionego warunku w WHERE...

Masz racje - trochę się zagalopowałem. Rozważam opcję gdzie usuwanie pewnych danych to usuwanie danych z kilku tabel (nie używam kaskadowego usuwania) więc najpierw pobieram selectem id (klucz) i usuwam np z kilu tabel. I ewentualnie dostaję warningi php że próbuję się odwołać do indeksu tablicy (brak wyniku - tablica pusta). To mogę rozwiązać dodając dodatkowego ifa.



Odświeżyłem temat bo dopadł mnie podobny problem (edycji przez więcej niż jednego usera).
Przykład: na stronie wyświetla się spis produktów. Każdy produkt niech posiada takie pola jak: nazwa, cena i opis.
Mamy dwóch użytkowników, którzy chcą edytować ten sam produkt, który posiada wpisaną nazwę i opis ale nie ma ceny.

Użytkownik A klika na edycję produktu i wyświetla się formularz. W tym samym czasie użytkownik B także klika na edycję tego samego produktu i wyświetla się formularz edycji.
Użytkownik A wprowadza cenę i zapisuje dane. Użytkownik B poprawia tylko opis, więc pole cena jest puste (kliknął edytuj zanim użytkownik A dodał cenę produktu) i zapisuje dane. Wynik cena wpisana przez użytkownika A znika.

W ostateczności zastosuję rozwiązanie, które podał dr_bonzo ale może macie sprawdzone sposoby (inne) radzenia sobie z takimi sytucjami?

@dr_bonzo: myślę, że taki znacznik, o którym piszesz mógłby być samą godziną rozpoczęcia edycji. To chyba najrozsądniejszy sposób.
dr_bonzo
Nie zaglebialem sie dokladnie w problem [ponownie], ale

Cytat
W ostateczności zastosuję rozwiązanie, które podał dr_bonzo ale może macie sprawdzone sposoby (inne) radzenia sobie z takimi sytucjami?


to masz na to wzorce projektowe
http://martinfowler.com/eaaCatalog/optimis...fflineLock.html
http://martinfowler.com/eaaCatalog/pessimi...fflineLock.html
a wzorce z definicji sa sprawdzone smile.gif no chyba ze nie rozwiaza twojego problemu to musisz dalej kombinowac
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.