concurrency in applikationen?

  • Ich bin gerade dabei, mir den Kopf darüber zu zerbrechen, wie man denn das Concurrency-Problem nicht nur auf MySQL-Ebene (Locks auf Datenbanken, Tabellen, Felder) sondern auch eine Stufe höher = auf (PHP-)Applikationsebene lösen könnte. Kennt jemand von Euch vielleicht hilfreiche Quellen (Artikel, Bücher) zu dem Thema?

    *** Make it idiot proof, and someone will build a better idiot. ***

  • vielleicht hab ich die Frage falsch formuliert, denn irgendwie ist wenig traffic bei diesem Thread ... ich versuch's jetzt nochmal, denn ich kann mir nicht vorstellen, dass bei den ganzen schlauen Leuten, die sich hier tummeln, sich noch keiner mit der Problematik beschäftigt hat und nicht zumindest einen paar Hints geben kann. ;)

    InnoDB von MySQL kann ja innerhalb der Transactions Locks auf bestimmte Datensätze setzen. Ähnlich verhält sich das Ganze ja auch mit bei PostgreSQL, wo man genauso mit "SELECT ... FOR UPDATE" usw. Locks setzen kann. Das löst das Problem auf der Skript-Ebene, d.h. damit kann ich z.B. verhindern, dass wenn ich über SELECT ein parent-Element gefunden hab und ich zu diesem ein child-Element anhängen will, dass das parent-Element in der Zwischenzeit nicht von einem anderen User gelöscht wird. So weit, so gut ...

    Jetzt hab ich aber ein Skript, dass im ersten Schritt mit einem SELECT die Daten (zB eines Kunden) herausliest. UserA tut dies bearbeitet die Daten aber so lange, dass ein UserB in der Zwischenzeit das gleiche Skript aufruft, die Daten schnell ändert und es submitted. Wenn nun die Daten von UserA auch submitted werden, dann würden ja die Änderungen von UserB verloren gehen, was noch nicht mal das schlimmste Szenario ist.

    Wofür ich jetzt dankbar wäre, sind hints, wie man diese Problematik, die sich ja nicht einfach über eine einzelne Transaktion lösen läßt (was ist wenn UserA über Nacht nach Hause geht, bevor er das Formular abschickt?), angehen könnte. Bitte, bitte, bitte. Ich hab im Google nach "concurrency", "transactions", "multiuser applications" usw. gesucht, aber irgendwie finde ich nicht die richtigen Schlagwörter um auf die richtigen Themen zu kommen. Ich kann mich mir nämlich nicht vorstellen, dass das Problem nicht ziemlich "beliebt" ist und man keine Lösungen finden kann, wenn man nur wissen würde, wo/wie man suchen muss.

    *** Make it idiot proof, and someone will build a better idiot. ***

  • Hä? Ganz verstehe ich das nicht.

    Ich probier mal zu erklären, was mir davon klar ist. Du willst also eine Art "Nein, geht nicht, weil User X das gerade tut"? So wie zB im Admin-Interface meines Routers, wo dann kommt "The Device is currently administered by X"?

    Ich würde sowas über die $_GLOBALS variable in php lösen. zB (ungetestet)

    Code
    if(empty($_GLOBALS['locks']))
      $_GLOBALS['locks']=array();
    
    
    if(is_locked($_GLOBALS['locks'][$id]))
      print_error();
    else {
      $_GLOBALS['locks'][$id]['time']=current_timestamp();
      $_GLOBALS['locks'][$id]['user']=current_user();
    }

    Das wird dann bei jedem Zugriff auf das Ding ausgeführt.

    is_locked() prüft dann einfach, ob $_GLOBALS['locks'][$id]['time']<(current_timestamp() + locking_time()) ist. locking_time könnte zB eine Stunde sein oder so.

    Wenn wer länger als eine Stunde auf das Ding nicht zugreift, hat er eben Pech gehabt und kriegt selber eine Fehlermeldung beim nächsten Versuch.

    Und wenn der ursprüngliche User seine Arbeit "ordnungsgemäß" beendet hat, wird der lock wieder gelöscht:

    Code
    unset($_GLOBALS['locks'][$id]);
  • Zitat von rck

    Hä? Ganz verstehe ich das nicht.

    Ich probier mal zu erklären, was mir davon klar ist. Du willst also eine Art "Nein, geht nicht, weil User X das gerade tut"? So wie zB im Admin-Interface meines Routers, wo dann kommt "The Device is currently administered by X"?

    Ich würde sowas über die $_GLOBALS variable in php lösen. zB (ungetestet)


    zunächst mal danke für's Mitdenken. :thumb: Allerdings ... ich glaube, wenn man diesen Ansatz verfolgt, dann müßte man die lock-time in der DB speichern und nicht in den GLOBALS, weil ja jeder User nur Zugriff aus seine GLOBALS hat und aus diesen nicht herauslesen kann, ob was jemand anderer in seinen GLOBALS stehen hat. Oder hast Du das anders gemeint?

    Und außerdem ... das würde bedeuten, dass ich in jeder Tabelle, in der Daten stehen, die potentiell von einem Multi-User-Edit betroffen sein können, noch eine Spalte haben müßte, in der drinnen steht, wann der Record gelockt worden ist. Und wenn ich überhaupt noch wissen will, wer denn gerade den Lock hat, dann müßte ich überall noch eine zweite Spalte mit idusers dazugeben.

    Das ganze wäre jetzt zwar eine Lösung, aber - nix für ungut - da muss es doch eine "automatischere" Lösung geben.

    EDIT: Die zusätzlichen Spalten ließen sich umgehen, in dem ich eine zusätzliche Tabelle mache, mit den Spalten table, key, locktime und idusers ... hört sich aber für mich noch immer nicht nach der feinen englischen Art an.

    *** Make it idiot proof, and someone will build a better idiot. ***

  • ähm wenns um webprogrammierung geht, wird das kaum bzw. sehr schwer in application ebene funktionieren - zumind. nicht automatisiert. immerhin läuft ja keine globale applikation am webserver oder?
    ansonsten darfst dir ein eigenes framework dafür basteln :)

    lg

  • Ich glaube nicht, dass das mit php funktioniert, müssest schon auf Java (jsp, servlets, etc.) umsteigen.

    mfG Fup

  • Zitat von maciek

    zunächst mal danke für's Mitdenken. :thumb: Allerdings ... ich glaube, wenn man diesen Ansatz verfolgt, dann müßte man die lock-time in der DB speichern und nicht in den GLOBALS, weil ja jeder User nur Zugriff aus seine GLOBALS hat und aus diesen nicht herauslesen kann, ob was jemand anderer in seinen GLOBALS stehen hat. Oder hast Du das anders gemeint?

    Nein, eben nicht! Die Sessions sind lokal je Session. Und die Globals global für den ganzen Apache. Zumindest glaub ich das so?

    Sonst: Shared memory :) Oder eine memory-tabelle in MySQL. Oder so irgendwas.

  • Zitat von rck

    Nein, eben nicht! Die Sessions sind lokal je Session. Und die Globals global für den ganzen Apache. Zumindest glaub ich das so?


    also ich glaub nicht, dass das so stimmt ... Du kannst als User X nicht auf die Globals eines Users Y zugreifen. Globals sind global über alle Funktionen und Methoden (z.B. $_POST oder $_SERVER), aber nur für den gegebenen User "einsehbar".

    Aber ich wäre bereit mich eines Besseren belehren zu lassen ... ;)

    *** Make it idiot proof, and someone will build a better idiot. ***

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!