Firebird hálózat-megszakadáskor LOCK-rollback

Firebird hálózat-megszakadáskor LOCK-rollback
2015-02-26T18:03:31+01:00
2015-03-11T21:34:55+01:00
2022-12-02T07:10:41+01:00
mandula
Sziasztok !
 Hogyan lehetne azt megoldani, hogy ha megszakad a wifi, vagy kirántják a kábelt, akkor a zárolt táblák X másodperc múlva feloldódjanak?

(Ha nem tudom szabályozni ezt az időt, az sem túl nagy baj, de azért 1-2 percnél ne tartson tovább.)

Ugyebár a Transaction timeout csak akkor működik, ha ÉL a kapcsolat, mert azt a Delphi kliens kezdeményezi egy sima beépített Timer segítségével.
Nekem az kellene, hogy az Adatbázis felismerje a "leszakadt" partnert, és vonja vissza a futó tranzakcióit.
(FB verz. 2.5.3)
Mutasd a teljes hozzászólást!
1. Hogyan azonosítsa egyedileg az adott programot?

CURRENT_CONNECTION egy integer ami egyértelműen azonosít minden kapcsolódást.
Egy táblába egy ilyen integer kulcsú tételt veszel fel/updateled percenként. 

select current_connection from rdb$database

2. Hogyan "lőjje ki" az adott (inaktív) programhoz tartozó ÖSSZES tranzakciót egy StoredProcedure

Törlöd a kapcsolatot.

DELETE FROM mon$attachments WHERE mon$attachment_id IN ( SELECT mon$attachment_id FROM mon$attachments WHERE mon$attachment_id = ***a_leakadt_kapcsolat_current_connection-je*** )
Bár mintha ez az SQL parancs keményen túl lenne komplikálva -- lenne egy fogadásom, hogy Oracle-n felnőtt programozó írta
 
Mutasd a teljes hozzászólást!

  • Az már szinte biztos, hogy ezt
    CURRENT_CONNECTION
    Illetve

    Create Trigger "Leszakadt_egy_kliens" ACTIVE ON DISCONNECT ...
    triggerrel kellene valahogyan megoldani.
    Mutasd a teljes hozzászólást!
  • Ott valami ping szerű megoldás kéne. A kliens egy táblába percenként csinál egy update-t , a szerveren meg egy futó szerviz figyeli a táblát és takarít a leszakadt kliensek után.
    Mutasd a teljes hozzászólást!
  • Kezdek aggódni, hogy ez egyáltalán nem is olyan egyszerű probléma...
    E szerint a hozzászólás szerint:

    Normally, Firebird uses SO_KEEPALIVE socket option to keep track ofactive connections. If you do not like default 2-hour keepalivetimeout then adjust your server OS settings appropriately. OnUNIX-like OS's, modify contents of /proc/sys/net/ipv4/tcp_keepalive_*. On Windows, follow instrutions of this article:Microsoft Support

    KÉT ÓRA a default disconnect idő minden Win* oprendszernél.
    Ezt azért le kellene tesztelni, hogy valóban ennyit vár-e.
    Elindítok egy tranzakciót, és meglátjuk... most van 18:37
    Mutasd a teljes hozzászólást!
  • Ez jó ötlet !
     Ötvözném még azzal, hogy nem kell a szerveren futnia a szolgáltatásnak,
    elég, ha a kliensek ellenőrzik  a "többieket". Elvégre ez csak akkor gond, ha más valaki akarja zárni a számlát.
    Arra gondoltam, hogy a "Connect" trigger végezhetné a takarítást... de ez talán túl nagy terhelés lenne a szervernek. Elég lenne, ha "lock conflict"-ba ütközés esetén a másik (vagy újraindított) kliens lefuttat egy Stored_Procedure-t.

    Már csak két problémát kell ehhez megoldani:
    1. Hogyan azonosítsa egyedileg az adott programot?
    Főleg úgy, hogy 1 gépen több példány is futhat. (Tehát az IP alapú azonosítás kizárva)

    2. Hogyan "lőjje ki" az adott (inaktív) programhoz tartozó ÖSSZES tranzakciót egy StoredProcedure?
    Mutasd a teljes hozzászólást!
  • MS SQL re csináltam hasonlót. Ott a kliensek kapcsolódáskor kaptak egy guid-t amit szépen beírtak a kapcsolat db-n belüli azonosítójával egy connect táblába (MSSQL hajlamos rá hogy egy új kapcsolatnak kiossza újra azt a kapcsolat id-t), míg egy másik táblában regisztrálták hogy milyen táblákat lockonak éppen, így minden adat megvolt a rendszertáblákban való takarításhoz ha x ideig nem adtak magukról életjelet. Firebirdnél is biztos megvan a lehetőség a rendszertáblákban egy process azonosítására és kilövésére.
    Mutasd a teljes hozzászólást!
  • 1. Hogyan azonosítsa egyedileg az adott programot?

    CURRENT_CONNECTION egy integer ami egyértelműen azonosít minden kapcsolódást.
    Egy táblába egy ilyen integer kulcsú tételt veszel fel/updateled percenként. 

    select current_connection from rdb$database

    2. Hogyan "lőjje ki" az adott (inaktív) programhoz tartozó ÖSSZES tranzakciót egy StoredProcedure

    Törlöd a kapcsolatot.

    DELETE FROM mon$attachments WHERE mon$attachment_id IN ( SELECT mon$attachment_id FROM mon$attachments WHERE mon$attachment_id = ***a_leakadt_kapcsolat_current_connection-je*** )
    Bár mintha ez az SQL parancs keményen túl lenne komplikálva -- lenne egy fogadásom, hogy Oracle-n felnőtt programozó írta
     
    Mutasd a teljes hozzászólást!
  • Köszi a kész kódot. Elfogadtam megoldásnak, hogy az utókor is okulhasson.
    (Amúgy a Current_Connection-t én is megtaláltam időközben, és TÉNYLEG egy szép kis int-et ad vissza.)

    Úgyhogy :
    1. generáltatok a klienssel a számla-záráskor egy GUID-t (mondjuk elég egy random int is, elvégre ha UNIQE-ra van állítva az oszlop, akkor úgy sem sikerül neki az insert :) )
    2. tíz másodpercenként update-elem
    3. ha másik kliens próbál számlát zárni, akkor az lefuttat kezdetnek egy Stored_procedure-t, ami mengnézi, hogy van-e fél percnél régebbi bejegyzés >> és ha van akkor törli azokat a tranzakciókat.
    4. Ha pedig mégsem volt megszakadás, akkor az eredeti kliens törli a "Lock-olásra" vonatkozó bejegyzést.
    Mutasd a teljes hozzászólást!
  • Qu> Köszönöm szépen az ötletet! Sajnos a pontot csak 1 valaki kaphatta és PONT ez a kód kellett, amit FBS írt.
    Mutasd a teljes hozzászólást!
  • Ui.: igen, a kód valóban túl van komplikálva helyesen valószínűleg simán elég:

    DELETE FROM mon$attachments WHERE mon$attachment_id = current_connection
    ... illetve MÉGSEM ! ... most látom, hogy van olyan is, hogy:
    mon$transactions
    ami hivatkozik az attachment táblára. Szerintem a kérdező ezt akarta írni:

    DELETE FROM mon$transactions T WHERE T.mon$attachment_id IN ( SELECT a.mon$attachment_id FROM mon$attachments A WHERE A.mon$attachment_id = ***a_leakadt_kapcsolat_current_connection-je*** )
    HELYESBÍTEK:
     ez is felesleges, mert a
    T.mon$attachment_id
    mindenhol egyforma :D Tehát valóban elég az a két parancs, hogy:

    DELETE FROM mon$transactions WHERE mon$attachment_id = :ID ;
    DELETE FROM mon$attachments WHERE mon$attachment_id = :ID ;
    Mutasd a teljes hozzászólást!
  • Tévedtem. Elég a "mon$attachments" táblából törölni. Sőt e szerint a bejegyzés szerint nem is lehet a transactions-ből:
    28.10.2014 03:34, avert <at> telusplanet.net wrote:
    > perhaps it takes some time for FB to delete the attachment?
    True.

    > can I delete from mon$transactions?
    No, you cannot.

    > can i delete from mon$attachments?
    Sure you can.

    Dmitry

    Márpedig Dmitry tudja mit beszél :D
    Mutasd a teljes hozzászólást!
  • Programból lehet hangolni, de mivel nem a te programod, csak a globális beállítás marad
    Windows: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\KeepAliveTime
    linux: /proc/sys/net/ipv4/tcp_keepalive_time
    Mutasd a teljes hozzászólást!
  • KÉSZ. Megcsináltam.
     érdekes fejlemény, hogy azért vannak gondok:

    Tehát úgy működik, hogy:
    1. valahányszor valaki elkezd zárni számlát,
    2. Zárolja azt (lock)
    3. feliratkozik egy "lockolasok" táblára
    4. Öt másodpercenként újra feliratkozik, felülírva a TimeStamp-et (időt)
    ...
    5. Ha megszakadt a kapcsolat
    6. egy másik gép, vagy egy újonnan elindított program (ugyanott) lefuttat egy StoredProcedure-t
     ami megnézi, van-e [2 percnél] régebbi bejegyzés
    7. és törli azokat a kapcsolatok a monitor táblából.
    ________________________________________
    NADE: ha másik gépről történt ez a feloldás >> CSAK onnan engedi újra zárolni,

    a "kifagyott" gépről (amit a másikról kényszerből "kilőttünk") utána már nem !!!
    Ráadásul ahogyan méregettem, az a 2 perc sem mindig pontosan annyi, inkább néha 3-4.
    Szóval fura módon valahogy lassan hajtja végre, kissé szelektív módon.

    Summa:
     - még mindig jobb, mint 2 órát várni, vagy a windos-registry-t módosítgatni.
     - de azért többet vártam... :( mert ez csak amolyan "működget" megoldás
       és ha nagy pörgés van, akkor idegesek lesznek a felhasználók, még 3 percet sem tudnak várni.
    Mutasd a teljes hozzászólást!
  • Én legelőször eltöprengenék azon, hogy miért is van szükség tábla szintű zárolásra. Ha jól van megszervezve az adatkezelés, a legritkább esetben kell táblát zárolni. Ha egy leszakadt tranzakció nincs COMMIT-al lezárva, akkor a többi tranzakció számára az olyan, mintha sosem létezett volna.
    Mutasd a teljes hozzászólást!
  • Úgy érted, hogy saját táblával és saját programmal megoldottad zárolást? Az jó dolog, ez a legflexibilisebb megoldás, viszont akkor nem értem a kérdésed: azért működik így vagy úgy, mert te így írtad meg... ha nem jó, keresd meg a hibát és javítsd ki.
    Mutasd a teljes hozzászólást!
  • Sajnos szükség van rekord szintű zárolásra, mert alkalmazás szinten rettenetesen bonyolult lenne minden lehetséges módon zárolni azon műveleteket, amit nem szabad már megtenniük a felhasználóknak, ha egyszer valaki megkezdte a zárási folyamatot. (Néha 1 munkamenetben többet is ... azaz sorozat-zárás)
    Az világos, hogy a Commit lefutása nem teljesül. De itt nem erről van szó, hanem a beragadt LOCK-okról.
    Mutasd a teljes hozzászólást!
  • saját táblával és saját programmal megoldottad zárolást?


    Nem, hanem úgy értem, hogy ötvöztem a kettőt.
    Azaz marad a számlák rekord-szintű lockolása, de ha leszakad egy kliens (pl. Wifi-megszakadás, vagy tablet-alvómód miatt,) akkor azt a lockolt számlát AZONNAL fel kell oldani egy másik programból.

    A sokféle hiba okára is fény derült időközben:
     - elfelejtettem TRUE-ra állítani a Timer-t , ami a LOCK-PING-eket küldte volna.

    (jelezve, hogy még ÉL a kapcsolat.) Ezért a másik program 2 perc után "kilőtte" a még futó tranzakciót.
    Már javítottam, és most kezdem tesztelni. Majd leírom a tapasztalatokat.
    Mutasd a teljes hozzászólást!
  • Jelentem, minden szép és jó és stabil.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd