Row Level Locking

Hallo an alle

Ich versuche einen ISAM -> PGSQL Wrapper zu schreiben um ein Programm das noch eine alte ISAM Datenbank benützt langsam nach PGSQL zu migrieren.
Lesen und schreiben funktioniert schon jetz brauche ich nur noch eine Möglichkeit das RowLevel Locking zu simulieren.
Bei ISAM ist es möglich sich einen LOCK zu hohlen und diesen später zu einem beliebigen Zeitpunkt zu releasen.
Leider habe ich bei PgSQL noch keine Möglichkeit gefunden dies nachzuahmen, da ich immer nur innerhalb einer Transaktion locken kann und diesen lock nur durch beenden einer Transaktion auflösen kann allerdings wären damit auch andere Locks verloren.
Hat jemand eine Idee wie ich das machen könnte?

In der Doku sind unter dem Kapitel “Explicit Locking” die verschiedenen Locking-Verfahren beschrieben. Darunter auch “Row-Level Locks”. Simulieren muss man diese Arts von Locks nicht, so etwas ist Standard in PostgreSQL!



mfg

fristo

richtig nur so wie ich die sache verstanden habe kann ich diese locks nur innerhalb einer Transaktion behalten.
Ich muss aber die Möglichkeit haben einen Lock zu halten auch wenn ich nicht in einer Transaktion bin.
Wie schon gesagt ist das Programm noch auf einer alten ISAM Datenbank also richtig mit direktem Zugriff auf IDX (index) und DAT (daten) files.
Hier funktionieren die Locks so das ich mir einen Lock auf n Zeilen in einer Tabelle hole und diesen Lock so lange halten kann wie ich möchte. Völlig Transaktionsunabhängig. Genauso kann ich jeden einzelnen Lock für sich wieder auflösen.

  1. Die Locks müssen unabhängig von Transaktionen sein
  2. Ich muss die Locks einzeln auflösen können
  3. Die Locks müssen verschwinden wenn der Client “stirbt”
  4. Es müssen ROW-Level Locks sein

Möglicherweise habe ich auch nur was überlesen kann mir jemand mal die SQL Statements geben die ich dafür brauche?

Du hast nichts überlesen, das ist in PostgreSQL nicht möglich.

Nein, in PostgreSQL ist die Transaktion defaultmäßig eingeschaltetet. Man kann sie auch abschalten. Aber was erreichst Du damit? Eine Transaktion sichert Dir die Konsistenz der Datenbank? Willst Du wirklich darauf verzichten?



Wenn Du die Transaktion abschaltetst, kannst Du die Locks explizit setzten.



Das kannst Du jederzeit auch mit PostgreSQL.



Vieles ist bei MySql aus der Historie gewachsen. Das ursprüngliche Ziel war ja nicht das heute mögliche. Ist es denn sinnvoll, außerhalb einer Transaktion eine Tabelle oder auch Zeilen einer Tabelle durch einen Lock zu sperren? Was ist, wenn ein Fehler auftritt? Eine Transaktion ist da immer die bessere und sichere Lösung. Viele, die bisher nur mit MySql gearbeitet haben, haben damit ihre Probleme. In den professionellen Datenbanken wird aber immer mit Transaktion gearbeitet. Vielleicht ist doch die Überarbeitung des bisherigen Designs sinnvoll.



mfg

fristo

Man kann Transaktionen in PostgreSQL abschalten?

hm, das wäre mir auch neu. ich weiß das man die transaction auf read-only setzen kann. das ist bei reinen selects u.u. vorteilhaft da ja postgresql meines wissens immer einen transaction-block mit BEGIN and COMMIT draus macht…

cu tb.

Ihr habt recht, da habe ich mich wohl an etwas falsches erinnert.


mfg

fristo

Daurauf verzichten will ich nicht. Aber im Moment ist das leider noch nicht möglich, da ich nicht genug Zeit habe die ganzen 50 Module umzustellen.
Nochmal zur Erklärung ich habe vorher NICHT mit MySQL gearbeitet. Eine ISAM Datenbank ist noch eine Ebene tiefer.Ich arbeite auf der Ebene auf der MySQL eure SQL Querys schon umgewandelt hat und direkt aus den Datendateien ausliest.
D.H. keine Query Language keine Relationen.
Man muss seine Keys selber durch Strukturen (struct) darstellen.

der code gehört teilweise zum vbisam projekt und ist unter der lgpl lizenziert.

die keystruktur&#58]

nur als kurzes beispiel.

Ein bekanntes Beispiel für eine solche Datenbank ist C-ISAM, eine Open Source Variante ist VB-ISAM [url]http://sourceforge.net/projects/vbisam[/url] wen es interessiert kann sich ja mal die Doku anschaun.....



[quote="fristo"]
Das kannst Du jederzeit auch mit PostgreSQL.[/quote]
Wie schon gesagt ich benutze kein MySQL im alten Source.



[quote="fristo"]
Vieles ist bei MySql aus der Historie gewachsen. Das ursprüngliche Ziel war ja nicht das heute mögliche. Ist es denn sinnvoll, außerhalb einer Transaktion eine Tabelle oder auch Zeilen einer Tabelle durch einen Lock zu sperren? Was ist, wenn ein Fehler auftritt? Eine Transaktion ist da immer die bessere und sichere Lösung. Viele, die bisher nur mit MySql gearbeitet haben, haben damit ihre Probleme. In den professionellen Datenbanken wird aber immer mit Transaktion gearbeitet. Vielleicht ist doch die Überarbeitung des bisherigen Designs sinnvoll.[/quote]
In dem Programm können sich mehrere Benutzer auf verschiedenen Stationen anmelden. Allerdings darf immer nur ein User auf der Station vorhanden sein. Mit C-ISAM haben wir einfach die Records der Station gelockt und waren somit sicher wenn der Client anbstürzt hebt das OS die Filelocks wieder auf und jemand anders kann sich einlocken......
Wenn ich in einer Tabelle speichere wer auf welcher Station eingelockt ist und mir der Client abstürzt oder auf andere Weise unnormal beendet wird kann sich niemand auf der Station mehr anmelden.
ICh brauche also eine Möglichkeit darauf zu reagieren wenn ein Client der irgendwo angemeldet ist plötzlich weg ist.
Ich hatte auf sowas wie einen Trigger gehofft wenn die Verbindung   von einem Client getrennt wird....aber leider nix gefunden. 

Irgendeine Idee?

mfg zbenjamin

Mal abgesehen von der Idee, das du dir ein eigenes PG Modul in C dafür schreibst …

Ansonsten fällt mir nichts ein, das dies mit PostgreSQL möglich wäre.

Was meinst du mit ein pg modul selbst schreiben???
Was denkst du kann ich damit machen?

mfg benjamin

Du kannst damit eigene Filesystem Locks erstellen, die auch nach dem Ende der Transaktion erhalten bleiben … C halt.

Wie das ganze aber letztendlich interagiert zwischen deiner DB und anderen Connections der gleichen DB … keine Ahnung. Hat wohl noch niemand probiert.

Die Doku liefert auch Anleitungen, wie man eigene Module schreibt, aber da scheinst du ja fit zu sein drin.

Hallo zbenjamin,

meine Annahme mit MySQL beruhte darauf, dass es früher in MySql auch ISAM-Tabellen gab und es Umsteiger von MySql nach PostgreSQL gibt.

Eine mögliche Lösung, die in ähnlicher Weise auch in der Praxis praktiziert wird, wäre, dass sich der aktuelle Client in regelmäßigen Abständen, z.B. alle 30 Sekunden, bei der Datenbank meldet und damit sagt “Ich lebe noch”. Jedesmal wenn sich der Client meldet, wird ein TIMESTAMPT aktualiert. Sind seit dem letzten TIMESTAMPT 30 Sekunden und mehr vergangen, kann man definieren, dass der Client abgestürzt ist.

Am einfachsten ist dieses mittels einer PL/pgSQL-Funktion zu realisieren, die dann vom Client aufgerufen würde.



mfg

fristo

Hm und wann lasse ich dann die überprüfung der ganzen timestamps laufen?
Also sowas wie cronjobs gibts ja bei pgsql nicht…
Bleibt also nur noch dir “wer sich vom programm abmeldet startet die aufräum funktion” methode oder?

Hallo zbenjamin,

Gute Frage an Jemand, die die Applikation, deren Strucktur und Aufbau und Funktion im Detail nicht kennt! Beschreibt doch mal in groben Zügen was das Programm macht und wie es eingesetzt wird. Und warum darf sich “nur ein User auf der Station vorhanden sein”? Was bezeichnest Du mit Station? Die Zugriffsberechtigung der User und deren Rolle in der Datenbank muss Du ja auch noch einrichten oder wie hast Du das bisher gelöst? Über den Lock?



mfg

fristo

Also das ganze ist ein Planungsprogramm um Mitarbeiterdienste zu planen.
Eine Station/Abteilung ist immer ein Dienstplan von Mo-So für alle Mitarbeiter die auf der Station/Abteilung arbeiten.
Wenn sich jetzt ein User auf einer solchen Abteilung anmeldet wird diese für andere Benutzer gesperrt, da diese sonst die neuen Eingaben des Users nicht sehen und die Daten sonst nicht konsistent sind. Bisher habe ich das mit einem Lock auf einen bestimmten Datensatz gelöst.
Wenn der Benutzer mit seinen Änderungen fertig ist und den Planungsbildschirm für die Abteilung schließt wird der Lock aufgehoben.
Ich benutze hier richtige Locks damit, sollte ein Client abstürzen oder jemand das Netzwerkkabel zieht das OS die locks freigibt.

Hmmm, wenn du mit einer Alternative leben kannst:

Es gibt im contrib Verzeichnis ein Modul namens userlocks oder so ähnlich. Das stellt Locks bereit, die auch länger als eine Transaktion laufen. Das sind allerdings nur virtuelle Locks, die nirgendwo fest auflaufen, deine Applikation müsste sich also überall an diese Locks halten, damit das funktioniert.

Hallo ads,

hast Du genauere Kenntnis wie die Anmeldung eines Users an den Server aussieht. Irgendwo, so meine Vorstellung, müssen doch Informationen über den angemeldenten User hinterlegt sein? Ich nehme mal an, in den Systemtabellen. Und was passiert, wenn die Netzverbindung unterbrochen wird? Bleibt der User immer angemeldet, oder wird nach einer bestimmten Zeit der User automtisch zurückgesetzt?

Vielleicht hat auch Xandrian nähere Kenntnisse.


mfg

fristo

Du hast ja pro Verbindung eines Users einen offenen Prozess. Dieser stirbt, sobald der User ausgeloggt wird, sein Programm abstürzt oder wie auch immer. Jedenfalls zum Ende der Datenbankverbindung.

Die Daten sind auch irgendwo in den Systemtabellen (pg_*) hinterlegt, aber das sind ja auch nur virtuelle Daten, die diese Informationen SQL-like einblenden.