ich brauche bitte etwas Hilfe bei folgender Aufgabenstellung: ein Kunde möchte eine lesende Sperre auf der Zeilenebene einer Tabelle realisieren. Die manuelle Zeilensperre gibt es laut der Postgre Dokumentation nur für schreibende Operationen. Die Rahmenbedingungen sind PostgreSQL 8.2 mit PHP frontend und Apache auf einem Ubuntu Server. De facto soll also folgendes passieren:
->Client A ruft eine bestimmte PHP Seite (formular.php) auf, die lesend (SELECT) auf eine Tabelle A zugreift. Dabei liest ein Client pro Aufruf von formular.php eine variable Menge von Datensätzen aus der Tabelle A, diese Teilmenge ist von den Aufrufparametern von formular.php abhängig.
->würde Client B versuchen die gleiche Teilmenge von Datensätzen zum approximativ gleichen Zeitpunkt aus der Tabelle A zu lesen (also die formular.php mit den gleichen Parametern aufzurufen, während Client A die formular.php noch geöffnet hat), soll eine Routine eingreifen, die das verhindert.
Ich müsste also eine Lesesperre auf Tabellenteile setzen, während ein Client eine PHP Seite geöffnet hat, und diese wieder lösen wenn er diese Seite verlässt. Nach schnellem Abklappern konnte ich kein Postgre-Bordmittel finden mit dem sich so etwas umsetzen lässt. Die Anforderung ist zugegebenermassen etwas exotisch, da die meisten mit den vorhandenen Mechanismen zur Wahrung der Integrität völlig zufrieden sind. Würde mich freuen, wenn einer der Kollegen dieser Herausforderung schon mal erfolgreich begegnet ist und mit Rat helfen kann.
Also erst mal heißt das PostgreSQL oder Postgres, nicht Postgre
Danach: hast du schon SELECT … FOR UPDATE gefunden?
Locks werden am Ende der Transaktion automatisch wieder freigegeben. Das impliziert, dass du deine Operationen innerhalb einer Transaktion durchführst.
Doch, Advisory Locks sind doch prima, vielen Dank. War in der von mir benutzten deutschen Handbuchversion nicht beschrieben. Demnach muss
pg_advisory_lock: locks an application-defined resource, which can be identified either by a single 64-bit key value or two 32-bit key values (note that these two key spaces do not overlap). The key type is specified in pg_locks.objid. If another session already holds a lock on the same resource, the function will wait until the resource becomes available. The lock is exclusive. Multiple lock requests stack, so that if the same resource is locked three times it must be also unlocked three times to be released for other sessions’ use.
das tun was ich will. Die Benutzung scheint allerdings so einfach zu sein, dass sie sich meinem Verständnis entzieht. Die pg_locks.objid enthält nach meinem Verständnis IDs der Einträge über bereits verhängte Sperren. Ich brauche allerdings eine ID für eine neue, die ich dem nach in die pg_locks erst reinbekommen muss? Katze beisst sich in den Schwanz. Habe ich einen Fehler in der Logik? Schon mal selbst vielleicht pg_advisory_lock benutzt?
Habe das hier gefunden: Merlin’s stuff: PostgreSQL 8.2 Advisory Locks
aber werde auch nicht schlau. Zu dem Parameter von pg_advisory_lock steht nur “…is completely application defined…”. Soll vermutlich heissen: man geht vom Vorhandensein des Sperre aus, die ID dieser soll durch die Anwendung bestimmt werden. Das stellt mich vor das gleiche Problem wie die Beschreibung im Handbuch. Danke noch mal für die Hilfe zur späten Stunde
Advisory Locks setzen da drauf, dass die Applikation sich daran hält. Das ist nichts, was vom Systen enforced wird.
Sprich, wenn eine Anwendung sich dran hält und die andere nicht, funktioniert das nicht.
Ansonsten, wie gesagt, kenne ich nichts, was dein Problem lösen würde.