TOCTTOU und ein paar Fragen zur Verhinderung
KlausStein
- datenbank
Hi,
ich muss leider in einigen Scripten mit Bezug auf die maximal vorhandene ID einer Tabelle arbeiten.
Deshalb locke ich die entsprechenden Tabellen vor der Arbeit und unlocke sie danach wieder.
Was passiert aber eigentlich, wenn bei gesperrten Tabellen der User im Scriptverlauf auf eine Fehlermeldung stößt, die nach Anzeige auch das Script stoppt.
Bleiben die Tabellen dann gelockt?
Sollte ich also in meine Fehlerfunktion ein unlock_tables einfügen? Aber unlockt das nicht dann auch ungewollt Tabellen, die von anderen Scripten gelockt wurden?
Wie geht man bei sowas vor?
Gruß, Klaus
Beispiel:
//-----------------------------------------------------------------------
// Tabellen sperren
//-----------------------------------------------------------------------
lock_table("tabelle1");
lock_table("tabelle2");
...
...
...
if (...) {
error("Fehlermeldung1");
}
....
....
....
//-----------------------------------------------------------------------
// Tabellen entsperren
//-----------------------------------------------------------------------
unlock_table("tabelle1");
unlock_table("tabelle2");
function error($Meldung) {
echo("$Meldung");
exit;
}
Ich glaube nicht dass der Unlock von selbst passiert wenn das Script fertig ist. Schau doch mal die Beschreibung dazu an. Tabellen sperren ist allgemein eine ziemlich tödliche Angelegenheit. Ich würd schauen dass du das umgehst wenn möglich.
Denk auch daran dass dein Script vielleicht mal mit einem Fehler total unkontrolliert abbricht.
Hello,
Deshalb locke ich die entsprechenden Tabellen vor der Arbeit und unlocke sie danach wieder.
Was passiert aber eigentlich, wenn bei gesperrten Tabellen der User im Scriptverlauf auf eine Fehlermeldung stößt, die nach Anzeige auch das Script stoppt.
Angeblich werden auch Datenbankhandles (seit PHP 5.??) wieder sauber aufgelöst, wenn die Variable, die dieses speichert ihre Gültigkeit verliert.
Bei Scriptabbruch (ohne dass PHP abstürzt) würde dies also geschehen. Theoretisch wäre damit die Funktion mysql_free_result() auch (nahezu) überflüssig.
Mit Schließen der Datenbank-Cennection werden aber auf jeden Fall die Locks auf den table aufgehoben. Achte bitte auch darauf, dass Du keine einzelnen Tabellen unlocken kannst, sondern nur alle Locks gemeinsam aufgehoben werden.
Seit MySQL 5.?? kann man sich aber oft mit einem Subselect das lästige Locken der Tabellen sparen. Dazu gab es neulich erst einen Thread hier, in dem ich das auch erst gelernt habe, dass es nun endlich funktioniert UND ZULÄSSIG IST.
Such mal nach "subselect" ...
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
Angeblich werden auch Datenbankhandles (seit PHP 5.??) wieder sauber aufgelöst, wenn die Variable, die dieses speichert ihre Gültigkeit verliert.
Bei Scriptabbruch (ohne dass PHP abstürzt) würde dies also geschehen. Theoretisch wäre damit die Funktion mysql_free_result() auch (nahezu) überflüssig.
Achso nochwas: Bei komplexeren DMS (datenverändernden Datenbankzugriffen) musst Du auf jeden Fall dafür sorgen, dass der angestoßene Prozess sauber zuende geführt wird, also bei einem Userabort also der User klappt noch bevor die Response (anfängt) einzutrudeln das Browserfnester zu.
Dafür sind die Funktionen ignore_user_abort() und ihre Verwandten da.
http://de3.php.net/manual/de/function.ignore-user-abort.php
Und ich würde das Zurückgeben von Handles auf jeden Fall immer sauber ausprogrammieren, auch wenn sich PHP inzwischen angeblich selber darum kümmert ;-P
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hi Tom,
Achso nochwas: Bei komplexeren DMS (datenverändernden Datenbankzugriffen) musst Du auf jeden Fall dafür sorgen, dass der angestoßene Prozess sauber zuende geführt wird, also bei einem Userabort also der User klappt noch bevor die Response (anfängt) einzutrudeln das Browserfnester zu.
Dafür sind die Funktionen ignore_user_abort() und ihre Verwandten da.
http://de3.php.net/manual/de/function.ignore-user-abort.php
Danke für diesen Hinweis,
ist es denn nicht sinnvoll, das einfach ins headerscript einzutragen, damit _immer_ alle Scripte sauber zuende geführt werden?
Oder hat das irgendwelche gravierenden Nachteile?
Grüße, KlausStein
Hello,
Achso nochwas: Bei komplexeren DMS (datenverändernden Datenbankzugriffen) musst Du auf jeden Fall dafür sorgen, dass der angestoßene Prozess sauber zuende geführt wird, also bei einem Userabort also der User klappt noch bevor die Response (anfängt) einzutrudeln das Browserfnester zu.
Dafür sind die Funktionen ignore_user_abort() und ihre Verwandten da.
http://de3.php.net/manual/de/function.ignore-user-abort.phpDanke für diesen Hinweis,
ist es denn nicht sinnvoll, das einfach ins headerscript einzutragen, damit _immer_ alle Scripte sauber zuende geführt werden?
Oder hat das irgendwelche gravierenden Nachteile?
Das würde ich nur bei DMS machen. Bei reinen Selects, also nicht verändernden Statements, ist es doch unnötig, noch aufwändig Ausgaben zu berechen, wenn der User sie nicht mehr sehen will. Überleg mal, was sonst mit der Anzahl von laufenden Prozessen passiert, wenn der User ein paarmal hintereinander seinen Aktualisieren-Button drückt am Browser.
Standardeinstellung ist allerdings: Script wird abgebrochen, wenn der User abortet.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Das würde ich nur bei DMS machen. Bei reinen Selects, also nicht verändernden Statements, ist es doch unnötig, noch aufwändig Ausgaben zu berechen, wenn der User sie nicht mehr sehen will. Überleg mal, was sonst mit der Anzahl von laufenden Prozessen passiert, wenn der User ein paarmal hintereinander seinen Aktualisieren-Button drückt am Browser.
Ok, das ist ein Argument.
Dann also doch mühsam 'rausklamüsern :-(
Danke für die Hilfe.
Klaus
Hello,
Das würde ich nur bei DMS machen. Bei reinen Selects, also nicht verändernden Statements, ist es doch unnötig, noch aufwändig Ausgaben zu berechen, wenn der User sie nicht mehr sehen will. Überleg mal, was sonst mit der Anzahl von laufenden Prozessen passiert, wenn der User ein paarmal hintereinander seinen Aktualisieren-Button drückt am Browser.
Ok, das ist ein Argument.
Dann also doch mühsam 'rausklamüsern :-(
Du kannst den aktuellen Zustand ja abfragen, ihn für die gekoppelten (zu koppelnden) Datenveränderungen auf "nicht abbrechen" einstellen und hinterher dann wieder auf den alten Zustand zurückstellen.
Im Prinzip müsste das in der Schnittstelle zur Datenbank in der API geschehen, also in den Funktionen, die das Model ansprechen. Ins Model gehört das wohl eher nicht.
Sollten mehrere manipuliernende Daten(bank)zugriffe stattfinden im Script, werden die ja bestimmt auch irgendwie wieder in einer Hüllfunktion stecken, sodass Du das dann dort vornehmen kannst.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hallo Tom,
Achte bitte auch darauf, dass Du keine einzelnen Tabellen unlocken kannst, sondern nur alle Locks gemeinsam aufgehoben werden.
Gut zu wissen. Ich dachte nämlich ich könnte einzelne Locks aufheben.
Seit MySQL 5.?? kann man sich aber oft mit einem Subselect das lästige Locken der Tabellen sparen. Dazu gab es neulich erst einen Thread hier, in dem ich das auch erst gelernt habe, dass es nun endlich funktioniert UND ZULÄSSIG IST.
Such mal nach "subselect" ...
DER war gut ;-)
Aber das Thema interessiert mich wirklich.
Schade, dass ich es bisher noch nicht finden konnte. Ich suche aber mal weiter.
Gruß, Klaus
Hello,
Such mal nach "subselect" ...
DER war gut ;-)
Aber das Thema interessiert mich wirklich.
Schade, dass ich es bisher noch nicht finden konnte. Ich suche aber mal weiter.
Im Prinzip war es dieser Thread
http://forum.de.selfhtml.org/archiv/2010/8/t199745/#m1344878
Kommt jetzt darauf an, was Du benötigst.
Eventuell hift Dir auch ein Trigger, der im Misserfolgsfall per absichtlich falschem Statement abgewürgt wird (falsche Spalte reicht). MySQL kennt mWn noch kein Throw_Userexeption.
Ob Triggers allerdings inzwischen mit ihrem Mutterstatement atomar zusammengefasst sind, überschaue ich im Moment auch nicht. Kann sein, dass da das nächste Problem steckt.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Im Prinzip war es dieser Thread
http://forum.de.selfhtml.org/archiv/2010/8/t199745/#m1344878
Hi Tom,
dank fürs Mitsuchen! :-)
Gruß, Klaus