Firebird + Delphi/C++ - update request

0

Witam
Czy w firebird'zie jest coś takiego jak hmm.. "update request"? Chodzi mi dokładnie o to, że mam aplikację klienta uruchamianą na wielu maszynach jednocześnie, która korzysta z zasobów jednej bazy. Jeżeli jeden użytkownik coś w niej zmieni, to nie chcę żeby inni użytkownicy pracowali na nieaktualnych danych, a tak będzie dopóki użytkownik nie odświeży sobie danych pobierając je na nowo (poprzez jakiegoś SELECT'a). Idealnym byłoby, żeby w momencie wykonania INSERT/UPDATE/DELETE firebird wysłał jakąś informację do wszystkich podłączonych transakcji, a komponenty odpowiedzialne za transakcję wywołały zdarzenie, które mógłbym obsłużyć. Czy da się coś takiego zrobić?

Będę bardzo wdzięczny za wszelkie uwagi, Pozdrawiam!

0

z tego co mi wiadomo żadna baza danych nie ma takiego mechanizmu. W FB możesz użyć eventów do tego - działają, sprawdzone. Musisz jednak sam zatroszczyć się o wywołanie eventu po zmianie danych.
Z drugiej strony jeśli masz np. 10 stacji klienckich i np. 9 z nich zacznie zmieniać często dane to ta biedna jedna stacja nie będzie robiła nic innego tylko odświeżała dane. BTW nie widziałem jeszcze aplikacji produkcyjnej, która by tak działała i nie było by to koniecznością

0

Jeśli korzystasz z IBX to dokładnie to o co pytasz realizuje IBEventAlert. Tutaj masz zajefajny opis mechanizmu eventów:

http://www.firebirdsql.org/doc/whitepapers/events_paper.pdf

Jak wspomniał Msiekd, automatyczne odświeżanie nie jest najlepszym pomysłem, ale można te eventy wykorzystać do zasygnalizowania, że przeglądany zbiór danych mógł ulec zmianie. Jeśli chcesz reagować na eventy jakimś zapytaniem do bazy, warto też wprowadzić małe losowe opóźnienie, żeby z n aplikacji w jednej chwili nie było wielu zapytań.

b

0

Jeśli zmiany następują często to takie automatyczne odświeżanie i tak niewiele pomoże, bo co z tego, że użytkownik dostanie aktualne dane, skoro w momencie zakończenia edycji rekordu one już będą nieaktualne co zatrzyma zatwierdzenie zmian albo po zatwierdzeniu nastąpi wycofanie transakcji? Jeśli zaś zmiany są rzadkie, wycofujemy transakcję i użytkownik za drugim razem powinien dać radę zmienić dane, w tym momencie odświeżone. Przy częstych zmianach można rozpatrzyć ustawienie zezwoleń na zatwierdzenie transakcji, jeśli inny użytkownik zmienia INNE pola rekordu zmienianego przez nas.

0
Mariusz Jędrzejowski napisał(a)

Jeśli zmiany następują często to takie automatyczne odświeżanie i tak niewiele pomoże, bo co z tego, że użytkownik dostanie aktualne dane, skoro w momencie zakończenia edycji rekordu one już będą nieaktualne co zatrzyma zatwierdzenie zmian albo po zatwierdzeniu nastąpi wycofanie transakcji? Jeśli zaś zmiany są rzadkie, wycofujemy transakcję i użytkownik za drugim razem powinien dać radę zmienić dane, w tym momencie odświeżone. Przy częstych zmianach można rozpatrzyć ustawienie zezwoleń na zatwierdzenie transakcji, jeśli inny użytkownik zmienia INNE pola rekordu zmienianego przez nas.

Teraz jakoś przyszło mi do głowy że OP chodziło faktycznie o coś innego. O to co napisałeś. W takim jednak wypadku, rozwiązaniem powinno być blokowanie rekordów na czas edycji. Czyli jak ktoś grzebie w rekordzie, to dopóki nie skończy inni mogą go tylko odczytywać takim jak był po ostatnim zapisie. Edycja będzie możliwa jak owy ktoś skończy swoje. Nie ma wówczas problemu pracy na "nieaktulanych" danych.

Nawet jeśli ktoś ma wyświetloną listę rekordów, a inny ktoś w między czasie zmieni jeden z tych rekordów i zapisze zmiany, i temu pierwszemu ktosiowi to się nie odświeży, to nic. Bo zwykle jest tak że pierwszy ktoś edytując później ten na pozór nie aktualny rekord pobierze na nowo dane do formatki edycji, i one będą już świeże (zakładają zrdoworozsądkowy poziom izolacji transakcji). Gorzej w przypadku pracy na jednym datasecie jako źródło do przeglądania i edytowania ... ale może i na to są sposoby - ja akurat tego typu rozwiązań nie stosuję.

b

0

Raczej rzadko się zdarzają sytuacje, żeby dane na innych końcówkach zmieniały się tak często, żeby to przeszkadzało danemu użytkownikowi. Często jest tak, że nawet zmiana tej samej kolumny w tym samym rekordzie nie powoduje konfliktu, bo transakcja zostaje wycofana, ale zaraz procedura odświeża rekord i ponawia transakcję (w pętli kilka razy) i zatwierdzenie udaje się zwykle za drugim razem. Oczywiście program musi być tak zrobiony, żeby sam reagował na niedopuszczalne wartości w tym polu (bo użytkownik już tego nie dostrzeże, gdyż odświeżenie nastąpi zaraz przed drugą transakcją). Takie rzeczy się stosuje na przykład gdy mamy do czynienia z przelewaniem jakiejś ilości towarów lub pieniędzy między jakimiś wewnętrznymi kontami.

Natomiast nie polecam (przy częstych konfliktach przez zmiany na innej końcówce) blokowania rekordu na cały czas edycji, która może trwać przecież kilkanaście minut albo dłużej, jeśli ktoś sobie wyjdzie z pokoju albo mu prąd wyskoczy na końcówce.

0
Mariusz Jędrzejowski napisał(a)

Natomiast nie polecam (przy częstych konfliktach przez zmiany na innej końcówce) blokowania rekordu na cały czas edycji, która może trwać przecież kilkanaście minut albo dłużej, jeśli ktoś sobie wyjdzie z pokoju
czy stosować optimistic czy pesimistic loock zależy wyłącznie od aplikacji i jej przeznaczenia. Może być tak, że część danych można blokować optymistycznie a część pesymistycznie. Dodatkowo dochodzą mechanizmy zdejmowania blokady i automatycznego anulowania edycji rekordu po określonym czasie od rozpoczęcia edycji lub od ostatniej akcji usera. Generalnie temat-rzeka i każdy przypadek trzeba rozpatrywać osobno. Jak sobie wyobrażasz realizację zamówienia przez wielu userów bez blokowania pesymistycznego?? Czyżbyś dopuszczał możliwość, że np 3 magazynierów zacznie realizować TO SAMO zamówienie i np. po 30 minutach dwóm z nich się nie uda zapisać mimo iż będą mieli towar np. na palecie? I co wtedy? - rozpakować z powrotem na magazyn? Chciałbym zobaczyć ich (magazynierów) miny :D

albo mu prąd wyskoczy na końcówce.
jak się końcówka zwiesza/wyłącza/cokolwiek to powinien nastąpić automatyczny rollback - wiele (o ile nie wszystkie) komponenty mają coś takiego jak DisconnectAction albo DefaultAction i to się ustawia na rollback

0

Blokadę realizuje się w nieco inny sposób, bo jest wygodniejszy (bez blokowania rekordów na poziomie bazy danych).

Wystarczy zmienić na początku status towaru na "w trakcie realizacji zamówienia". On zostaje w ten sposób zarezerwowany i na innej końcówce aplikacja wie, że nie wolno już go zarezerwować. Timer cyklicznie sprawdza na przykład co godzinę, czy są zarezerwowane towary i je wycofuje, ale najczęściej w międzyczasie on już zmienia status na "oczekujący na wpłatę" i wtedy timer wycofa go dopiero po kilku dniach, chyba że wpłynie należność i wtedy status zmienia się na "sprzedany".

0

i jak się końcówka wypieprzy to mamy towar "w trakcie realizacji zamówienia" już na zawsze. Oczywiście można dodawać np. znacznik czasu i funkcje, które automatycznie zdejmują blokadę po np 1h czy wręcz napisać osobną aplikację, która będzie działała 24h/dobę 7dni/tydzień i zdejmowała "niechciane" blokady. Można też zatrudnić kogoś, kto będzie tylko przeglądał blokady tak założone i sprawdzał czy jest ona faktycznie potrzebna, itd, itp, ... Pewnie że można robić to "na piechotę", "ręcznie" i "od d**y strony". Generalnie można nawet zrezygnować z bazy danych na rzecz plików typowanych czy wręcz tekstowych. A jaka wygoda - byle notatnikiem możesz sobie pogrzebać w danych i być "hakierem"... Wszystko można tylko pytanie jest po co? Po co wymyślać koło na nowo?

0

To co opisałem to jest standardowe postępowanie, które jest opisywane w książkach z przykładami z php jak "Practical PHP
and MySQL - Building Eight Dynamic
Web Applications" autorstwa Jono Bacon. Rekord nie jest zablokowany przez transakcję, więc blokada zostanie zdjęta po upływie czasu "karencji" przez timer (przecież klient może nie wpłacić za towar nawet po kilku dniach). Również można dorobić dodatkowe procedury, które zmienią status towaru w razie awarii.

Transakcji nigdy nie powinno się zostawiać działającej na czas minut a jedynie na chwilę (milisekundy).

0

ale o czym ty tu w ogóle piszesz?? Jaki php?? WebApp a desktop to są całkiem odmienne dziedziny i podejście w nich jest całkiem inne.

BTW jak się już uczepiłeś tak tego towaru to w normalnych programach jest tak

  1. pojawia się zamówienie - towar zostaje zarezerwowany albo i nie - zależy od sposobu działania firmy
  2. towar jest wydawana - schodzi ze stanu magazynowego niezależnie czy został zapłacony czy nie! Fizycznie go już przecież nie ma
  3. faktura/paragon zostaje zapłacony
    koniec, tyle. Stan magazynu a stan płatności klienta nie ma ze sobą nic wspólnego. Tak samo jak m nie nie interesuje za jaki towar klient nie zapłacił - mnie interesuje ile w sumie mi klient wisi i na tej podstawię podejmuje decyzje czy zaufać mu i sprzedać coś jeszcze czy nie.

Co mi da ten twój timer, że mi w bazie odznaczy towar jako wydany jak ja go fizycznie miał nie będę? Może czas zostawić książki i zobaczyć jak rzeczywisty świat działa, jakie wymagania są stawiana programom magazynowo-sprzedażowym (wnioskuję, że o takich mówisz), jak działa proces zamówienie-realizacja-wydanie-płatność-zwrot w normalnym obrocie zarówno detalicznym jak i hurtowym.

No i na koniec chciałbym zobaczyć jak tłumaczysz klientowi, któremu sprzedałeś swoją app, że ten towar jest na stanie magazynowym dlatego, że klient jeszcze za niego nie zapłacił, a to że fizycznie ten towar już dawno jest u klienta to drobiazg...

0
Misiekd napisał(a)

Może czas zostawić książki i zobaczyć jak rzeczywisty świat działa

Kiedyś wiedza książkowa była czymś w miarę pewnym. Teraz nawet książki zeszły na psy. Ze dwa razy się naciąłem na taki shit. Pewnym można być tylko wiedzy opartej na doświadczeniu, a nie na teorii....

b

1 użytkowników online, w tym zalogowanych: 0, gości: 1