Texter mit x: Session-Daten Schreib- oder Schreib-Lese-Sperre?

http://de.php.net/manual/de/function.session-write-close.php

Bekommen Session-Daten wirklich nur eine Schreibsperre oder auch eine Lesesperre?

Falls sie nur eine Schreibsperre bekommen: Kann man aus dem script heraus feststellen, ob (k)eine Schreibsperre besteht oder "muß" man prophylaktisch was in die Session schreiben, damit man erst danach was lesen kann, weil man die Schreibrechte bekommen hat und durch den Schreibvorgang andere Zugriffe eine Schreibsperre haben?

  1. Hi,

    Bekommen Session-Daten wirklich nur eine Schreibsperre oder auch eine Lesesperre?

    Falls sie nur eine Schreibsperre bekommen: Kann man aus dem script heraus feststellen, ob (k)eine Schreibsperre besteht oder "muß" man prophylaktisch was in die Session schreiben, damit man erst danach was lesen kann, weil man die Schreibrechte bekommen hat und durch den Schreibvorgang andere Zugriffe eine Schreibsperre haben?

    Selbst wenn du so vorgehen würdest - deine neu in die Session gesteckten Daten würden erst dann wirklich *geschrieben*, wenn du session_write_close aufrufst (oder das Script zu Ende ist, was implizit den Schreibvorgang auslöst). Dann kannst du dann aber auch erst wieder neu lesen, wenn du die Session neu aufnimmst - und selbst wenn dir das in der selben Scriptinstanz gelingt, könnte ein anderer Prozess inzwischen einen Lock haben.

    Wäre noch zu untersuchen, wie sich das ganze verhält, wenn du session_regenerate_id einsetzt. Damit muss die Session-Datei auf jeden Fall neu geschrieben (oder umbenannt) werden.

    MfG ChrisB

    --
    Light travels faster than sound - that's why most people appear bright until you hear them speak.
    1. Oh, ich wollte "Bekommen Session-Dateien wirklich nur eine Schreibsperre oder auch eine Lesesperre?" und nicht "Session-Daten" schreiben. Ich hoffe jetzt reden wir nicht aneinander vorbei, ich warte daher erst mal auf Klärung.

      Falls sie nur eine Schreibsperre bekommen: Kann man aus dem script heraus feststellen, ob (k)eine Schreibsperre besteht oder "muß" man prophylaktisch was in die Session schreiben, damit man erst danach was lesen kann, weil man die Schreibrechte bekommen hat und durch den Schreibvorgang andere Zugriffe eine Schreibsperre haben?

      Selbst wenn du so vorgehen würdest - deine neu in die Session gesteckten Daten würden erst dann wirklich *geschrieben*, wenn du session_write_close aufrufst (oder das Script zu Ende ist, was implizit den Schreibvorgang auslöst). Dann kannst du dann aber auch erst wieder neu lesen, wenn du die Session neu aufnimmst - und selbst wenn dir das in der selben Scriptinstanz gelingt, könnte ein anderer Prozess inzwischen einen Lock haben.

      Das heißt, wenn ich eine session starte (mit session_start(), eine Session die schon läuft), dann werden die Session-Daten aus der Session-Datei in den Speicher geladen, es erfolgt dadurch aber keine Sperre die über das Laden hinaus anhält?

      Nun kann ich die Session-Daten (im Speicher) verändern. Die ursprünglichen Daten können aber währenddessen über einen anderen script-Aufruf auch aus der Session-Datei geladen, verändert und (wörtlich) früher oder später wieder in die Session-Datei geschrieben werden?

      Die Sperre besteht nur (wieder?), wenn am scriptende bzw. bei function.session-write-close die Session-Daten aus dem Speicher in die Session-Datei geschrieben werden?

      Dann verstehe ich folgenden Hinweis nicht: "Bei der Verwendung von Framesets zusammen mit Sessions werden Sie merken, dass wegen dieser Sperrung ein Frame nach dem anderen geladen wird. Sie können die Zeit zum Laden aller Frames reduzieren, indem Sie die Session beenden, sobald alle Änderungen an den Session-Variablen durchgeführt sind."

      Für mich hört sich das so an, als ob die anderen script-Aufrufe warten müßten und auch warten. Warten aber nicht auf das Fertiglesen* nach Lesestart, auch nicht warten auf das Fertigschreiben* nach Schreibstart, sondern warten auf die Abarbeitung des scriptes, welches die Session-Daten eher aus der Session-Datei gelesen hat. Damit nicht auf die Abarbeitung gewartet werden muß, soll man function.session-write-close einsetzen.

      * Was sicherlich relativ schnell geht.

      Ich warte hierzu erstmal Klarheit ab, bevor ich auf die anderen Beiträge reagiere.

      1. Hi,

        Das heißt, wenn ich eine session starte (mit session_start(), eine Session die schon läuft), dann werden die Session-Daten aus der Session-Datei in den Speicher geladen, es erfolgt dadurch aber keine Sperre die über das Laden hinaus anhält?

        Doch.
        Und zwar eine, die bis zum Scriptende oder dem vorzeitig ausgelösten Speichern der Session-Daten in die Session-Datei anhält.

        Für mich hört sich das so an, als ob die anderen script-Aufrufe warten müßten und auch warten. Warten aber nicht auf das Fertiglesen* nach Lesestart, auch nicht warten auf das Fertigschreiben* nach Schreibstart, sondern warten auf die Abarbeitung des scriptes, welches die Session-Daten eher aus der Session-Datei gelesen hat.

        Nein, bis das Script, dass die Sessiondatei zuvor hat öffnen lassen, diese wieder schliesst - durch explizites Wegschreiben, oder durch impliztes am Scriptende.

        Damit nicht auf die Abarbeitung gewartet werden muß, soll man function.session-write-close einsetzen.

        Ja.

        Wenn du mit dem, wo für du die Session brauchst, fertig bist - anschliessend als nur noch bereits gelesene Werte brauchst, aber keine neuen mehr wegschreiben willst - dann solltest du sie mit session_write_close schliessen (und damit für andere Scriptinstanzen freigeben). Natürlich nur, wenn dein Script danach noch zeitaufwendige Sachen macht. Wenn es nur noch eine Ausgabe macht, bevor es sich selbst beendet, dann kann man darauf auch verzichten.

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
        1. Doch.
          Nein, ...
          Ja.

          Dann habe ich dich falsch verstanden und es ist alles so wie ich es erhoft habe.

  2. Hello,

    http://de.php.net/manual/de/function.session-write-close.php

    Bekommen Session-Daten wirklich nur eine Schreibsperre oder auch eine Lesesperre?

    Falls sie nur eine Schreibsperre bekommen: Kann man aus dem script heraus feststellen, ob (k)eine Schreibsperre besteht oder "muß" man prophylaktisch was in die Session schreiben, damit man erst danach was lesen kann, weil man die Schreibrechte bekommen hat und durch den Schreibvorgang andere Zugriffe eine Schreibsperre haben?

    Session-Daten bekommen ein advisory LOCK_EX, das solange aufrechterhalten wird, bis das Script beendet wird (genau, bis es seine Sessiondaten geschrieben hat).

    Du kannst also ein fopen() auf die Sessiondatei ausüben, nur kein flock(), egal ob mit LOCK_SH oder LOCK_EX. Das bedeutet also, dass Du das aus einem anderen Script nur sinnvoll testen kannst, wenn Du

    $fh = fopen('frenmde_Sessiondatei', r+);

    if ($fh)
        {
            $lock = flock($fh, LOCK_EX | LOCK_NB, $wouldblock ))
        }

    if ($lock)
        {
            ## Arbeitsschritte durchführen

    }
        else
        {
            ## Fehlerbehandlung
        ]

    fclose($fh);

    oder auch mit LOCK_SH, wenn Du selber nicht schreiben willst, auch nicht später!
    Denke daran, dass der Lesevorgang für die sofort anschließende Datenveränderung immer innerhalb des gemeinsamen LOCK_EX stattfinden darf. Ggf. musst Du nochmal lesen, wenn Du vorher schon für rein informative Zwecke unter LOCK_SH gelesen hast.

    Wenn Du mit Session_write_close() die Sesseiondatei schließt, gilt das ebenfalls sinngemäß.
    Solltest Du die Sessiondatei nochmals wieder öffen wollen zur Benutzung, muss das Session-Array neu aufgebaut werden innerhalb des LOCK_EX, denn es könnte ja ein erlauchter Vorgesetztenprozess in der Zwischenzeit in die Sessiondatei hineingeschrieben haben, warum auch immer ...

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hello,

      nur nochmal zur Klarstellung. Da stand vorher was von "nicht... darf" und das wurde dann zu MUSS:

      Denke daran, dass der Lesevorgang für die sofort anschließende Datenveränderung immer innerhalb eines gemeinsamen LOCK_EX stattfinden [steiche:darf] muss. Ggf. musst Du nochmal lesen, wenn Du vorher schon für rein informative Zwecke unter LOCK_SH gelesen hast.

      Aber Sven hatte es ja auch nochmal auf den Punkt gebracht. Die Sache mit der Datenbank wird übrigens auch im normalen Betrieb immer gerne vergessen bzw. überhaupt nicht berücksichtigt.

      Deshalb hatten wie ja neulich schon einen Thread in dem ich nach einem Hash über den ganzen Datensatz gefragt hatte, um den Conflict Counter zu vermeiden...

      Das ist nämlich immer dann von Interesse, wenn man auf fremde Datenbanken zugreifen muss, die ungenügend vorbereitet sind.

      Ich verwende für meine Lösungen immer Trigger, die beim Update den Conflict Counter automatsich hochsetzen. Die kann man dann auch nicht umgehen. Wenn man dann noch eine Stored Procedure drum herum packt, kann man ohne Kenntnis über den passenden Conflict Counter gar kein Update mehr durchführen.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
    2. Session-Daten bekommen ein advisory LOCK_EX, das solange aufrechterhalten wird, bis das Script beendet wird (genau, bis es seine Sessiondaten geschrieben hat).

      Du meinst die Datei mit den Session-Daten?!

      Was mir nun nicht klar ist, muß ich dafür sorgen, daß sie einen advisory LOCK_EX bekommt, oder passiert das automatisch durch session_start() (oder den ersten Zugriff auf eine Sessionvariable)?

      Im letzteren Fall ist es also nicht so, wie ich dort gerade nachfrage ob es so ist, daß die Sperre jeweils nur für den Lese- und Schreibvorgang besteht.

      1. Hi,

        Was mir nun nicht klar ist, muß ich dafür sorgen, daß sie einen advisory LOCK_EX bekommt, oder passiert das automatisch durch session_start() (oder den ersten Zugriff auf eine Sessionvariable)?

        Wenn du den dateibasierten Standard-Sessionhandler von PHP benutzt, dann musst du dich ums Locking nicht selber kümmern, das ist bereits "eingebaut".

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
        1. Dann nutze ich diesen Zweig, wo zwei vertreten sind, um den drei Antwortenden zu danken.

          Danke.

      2. Hello,

        Session-Daten bekommen ein advisory LOCK_EX, das solange aufrechterhalten wird, bis das Script beendet wird (genau, bis es seine Sessiondaten geschrieben hat).

        Du meinst die Datei mit den Session-Daten?!

        Jaaa verdammt! :-)

        Was mir nun nicht klar ist, muß ich dafür sorgen, daß sie einen advisory LOCK_EX bekommt, oder passiert das automatisch durch session_start() (oder den ersten Zugriff auf eine Sessionvariable)?

        Das geschieht automatisch bei session_start().

        Im letzteren Fall ist es also nicht so, wie ich dort gerade nachfrage ob es so ist, daß die Sperre jeweils nur für den Lese- und Schreibvorgang besteht.

        Nein, das wäre ja fatal. Die Sperre muss über die gesamte Zeit bestehen, innerhalb der dann glesen und geschieben wird, auch wenn zwischenduchr Warte- oder Verarbeituntszeit vergeht.

        Das gilt aber für alle Daten- oder Strukturverändernden Lese-Schreibvorgänge, die im Wettbewerb mehrerer Prozesse (auch von einem User) stehen.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Jaaa verdammt! :-)

          Was erklärt ihr auch so viel, verdammt, "auch Lesesperre" hätte doch ausgereicht. ;-)

          ChrisB hat mich total verwirrt. Es hätte ja sein können, daß bei session_start() nur eine Schreibsperre ohne Lesesperre gesetzt wird, die erst mit der Abarbeitung des scriptes beendet wird. Dann könnte man vor dem ersten Lesen einfach was schreiben und hätte so aus einer Quelle gelesen, die bis zum scriptende und damit bis zum Zurückschreiben von nichts verändert werden kann. Für alle anderen Aufrufe würde das Gleiche gelten.

          Im letzteren Fall ist es also nicht so, ... daß die Sperre jeweils nur für den Lese- und Schreibvorgang besteht.

          Nein, das wäre ja fatal.

          Was aber nicht bedeutet, daß es nicht so umgesetzt sein könnte. Als jemand der auch auf Systemen programmiert bei denen er mögliche Glichtes/Hazards berücksichtigen muß, wollte ich mich nicht auf die Vermutung verlassen, daß in der Schreibsperre eine Lesesperre enthalten ist. Ich hatte die Vermutung noch nicht mal nur die Hoffnung.

          1. Hello,

            es könnte so umgesetzt werden, dass

            beim Session_start() ein LOCK_SH gesetzt wird. Damit könnte jeder Prozess, auch wenn er sich an die Lockingstrategie hält, die Datei noch lesen.

            Wenn jetzt in die Session geschrieben werden soll, dann müsste das Script versuchen, die Sperre vorher auf LOCK_EX hochzusetzen und könnte dann erst schreiben und die Sperre dann wieder herabsetzen auf LOCK_SH. Das Hochsetzen auf LOCK_EX geht aber nur dann, wenn kein anderes Script inzwischen auch ein LOCK_SH auf die Datei hält.

            Da das relativ aufwändig zu implementieren wäre (PHP ist ja noch in C geschrieben und nicht in C++, wo Überladung von Opratoren möglich ist) und es außerdem im Betrieb denselben wahrscheinlich eher aufhalten würde, als einen wirklichen Nutzen zu liefern, hat man es wohl lieber gelassen...

            Außerdem sollten wir nicht vergessen, dass auf Unixoiden OS ohnehin nur ein advisory Lock benutzt wird, das dann einfach missachtet werden kann, wenn ein anderer Prozess unbeding lesen will. Schreiben wäre allerdings eine Sauerei von dem bösen Prozess :-))

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Und schon erklärt er wieder irgenwas und ich weiß nicht wieso. ;-)

              1. Hello,

                Und schon erklärt er wieder irgenwas und ich weiß nicht wieso. ;-)

                Weil Du danach gefragt hast, ob auch anders gesperrt werden könnte?

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. Und schon erklärt er wieder irgenwas und ich weiß nicht wieso. ;-)

                  Weil Du danach gefragt hast, ob auch anders gesperrt werden könnte?

                  Fragst Du, ob die Erklärung dafür warum "ich nicht weiß wieso" darin liegt, daß ich gefragt habe, ob auch anders gesperrt werden könnte?

                  Oder sagst Du, daß Du was erklärt hast, weil ich gefragt habe, ob auch anders gesperrt werden könnte?

                  Hm, dabei habe ich doch gar nicht gefragt, ob auch anders gesperrt werden könnte.

                  1. Hello,

                    Hm, dabei habe ich doch gar nicht gefragt, ob auch anders gesperrt werden könnte.

                    Dein Fragestil ist zugegebenerweise sehr implizit.
                    https://forum.selfhtml.org/?t=192045&m=1281287

                    Das ist aber heutzutage leider normal, dass Menschen keinen Mut haben, eine echte Frage zu stellen, deren Antwort für sie auch "nach hinten" losgehen könnte.

                    Daraus entstehen dann solche Konstruktionen, wie "ich seiß ja nicht, ob Sie das intereiisert, aber...", statt dass man fragt: "Interessiert Sie die Angelegenheit? Darf ich ihnen mehr darüber erzäheln? Was wollen Sie genau wissen?"

                    Wenn Dich das nun genauer interessiert, was kann ich dann für dich tun?

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                    Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
                    1. Hm, dabei habe ich doch gar nicht gefragt, ob auch anders gesperrt werden könnte.

                      Dein Fragestil ist zugegebenerweise sehr implizit.
                      https://forum.selfhtml.org/?t=192045&m=1281287

                      Bahnhof. Meinst Du vielleicht den letzten Satz, an dessen Ende tatsächlich ein Fragezeichen gehört hätte?

                      Das ist aber heutzutage leider normal, dass Menschen keinen Mut haben, eine echte Frage zu stellen, deren Antwort für sie auch "nach hinten" losgehen könnte.

                      Bahnhof die Zweite.

  3. Moin!

    http://de.php.net/manual/de/function.session-write-close.php

    Bekommen Session-Daten wirklich nur eine Schreibsperre oder auch eine Lesesperre?

    "Nur" ist die falsche Wortwahl. Eine Schreibsperre ist eine exklusive Sperre (bei flock das LOCK_EX), d.h. zeitgleiche Lesezugriffe werden unterbunden.

    Siehe auch die englische Dokuseite von session_write_close(), die das verdeutlicht: "...but as session data is locked to prevent concurrent writes only one script may operate on a session at any time."

    Das Sperren einer Session gegen gleichzeitige Schreibvorgänge wird übrigens gerne vergessen, wenn man eigenständige Session-Handler (zum Schreiben in die Datenbank) verwendet. Zwar wird in diesem Fall keine Zerstörung von Daten durch unkoordiniertes gleichzeitiges Schreiben in eine Datei stattfinden, aber definitiv können zwei Skripte fast zeitgleich gestartet werden, dann dieselben Daten laden, jeweils unterschiedlich abändern, und am Ende überlebt nur die eine Änderung, die zuletzt in die Datenbank zurückgeschrieben wurde.

    Mit solchen schwer zu debuggenden Race-Conditions kann man sich ziemlich fiese Probleme einhandeln.

    Und schon allein aus dieser Überlegung heraus ist klar, dass das Verwenden einer Datei zwingend exklusives Locking voraussetzt. Das ist übrigens exakt der Fall "Datei einlesen und verändert später wieder speichern" aus dem Artikel "Sperren von Dateien".

    - Sven Rautenberg

    1. Siehe auch die englische Dokuseite von session_write_close(), die das verdeutlicht: "...but as session data is locked to prevent concurrent writes only one script may operate on a session at any time."

      Wenn ich das in Englisch ausreichend sicher mit allen Feinheiten verstehen würde, müßte ich vielleicht nicht fragen. Das habe ich aber auch verschwiegen. Anderweitig hatte ich aber auch nach einer Antwort gesucht.

      Und schon allein aus dieser Überlegung heraus ist klar, dass das Verwenden einer Datei zwingend exklusives Locking voraussetzt. Das ist übrigens exakt der Fall "Datei einlesen und verändert später wieder speichern" aus dem Artikel "Sperren von Dateien".

      Den Artikel kenne ich und ich habe das an anderer Stelle auch schon mal umgesetzt. Was mir nicht bewußt war, war, daß es bei der Session-Datei-Sperre genau so passiert.