eintrag kurzzeitig verweigerb
peter müller
- datenbank
hallo
ich habe eine datenbank (mysql), in der bestellungen von benutzern eingetragen werden sollen.
nun bevor der eintrag gespeichert wird, soll überprüft werden, ob noch eine genügende anzahl vorhanden ist (schritt 1). danach soll die reservation getätigt werden (schritt 2).
zu meiner frage: wie kann ich verhindern, dass ein anderer benutzer zur fast gleichen zeit (zwischen schritt 1 und 2) eine reservation vornimmt, so dass das programm meint es sei noch eine genügende anzahl vorhanden, da schritt 2 vom ersten benutzer noch nicht ausgeführt wurde?
kann ich den insert-befehl zwischenzeitlich blockieren?
besten dank
peter
Hallo Peter,
da gibt es
GET_LOCK(name,time)
...checken
...inserten
release_lock(name)
Es wird nicht wirklich gelockt, sondern diese Locks werden nur in eine Advisory Table eingetragen. Jeder Prozess, der nun schreiben will, sollte also versuchen, den Lock mit dem Namen zu bekommen und wenn das nicht klappt, dann nach time nochmal wiederkommen.
Mach Dir Konstanten für name und time, damit auch wirklich alle Prozesse die selben benutzen und greif aus jedem Prozess immer nur über eine Hüllfunktion,
z.B
checked_insert($tablename,$data,$con)
{
wenn nicht GET_LOCK(name,time) dann return false;
...checken
...inserten
release_lock(name)
return true;
}
Grüße
Tom
besten dank für den tipp. es ist mir aber nicht ganz klar, wie ich die befehle mit php verwenden kann.
folgendes funktioniert nicht:
$sql='select get_lock ("name",1000)';
mysql_query($sql);
$sql = "insert into tabelle (von) values ('name')";
mysql_query($sql);
wie kann ich diese abfrage mit php ausführen?
wenn nicht GET_LOCK(name,time) dann return false;
besten dank
peter
besten dank für den tipp. es ist mir aber nicht ganz klar, wie ich die befehle mit php verwenden kann.
folgendes funktioniert nicht:
probier mal das:
$sql = 'get_lock ("name",1000)';
$res = mysql_query($sql);
if (!$res)
{
echo mysql_error();
exit;
}
$sql = "insert into tabelle (von) values ('name')";
mysql_query($sql);
$ok=mysql_query("release_lock("name");
Hallo nun zur guten Nacht,
also gut, ohne select gehts nicht.
function cheched_insert( ...)
{
$sql = 'get_lock ("name",1000)';
$res = mysql_query($sql);
if ($res)
{
$sql = "insert into tabelle (von) values ('name')";
mysql_query($sql);
$ok=mysql_query("release_lock("name"); echo mysql_error();
return mysql_affected_rows($con);
}
else
{
return false;
}
}
Hallo nun zur guten Nacht,
also gut, ohne select gehts nicht.
function cheched_insert( ...)
{$sql = 'select get_lock("name",1000)';
$res = mysql_query($sql);if ($res)
{
$sql = "insert into tabelle (von) values ('name')";
mysql_query($sql);
$ok=mysql_query("select release_lock("name"); echo mysql_error();
return mysql_affected_rows($con);
}
else
{
return false;
}}
soweit hats funktioniert. nun wollte ich das ganze mal testen und habe
ok=mysql_query("select release_lock("name");
echo mysql_error();
weggelassen. bei jedem reload der seite wurden die einträge dennoch getätigt. was muss ich nich ändern, damit dies nicht passiert?
peter
Hallo Peter,
das Release_lock() solltest Du auf keinen Fall weglassen, auch wenn ein sauberes PHP das Lock bei Ende des Scriptes automatisch aus der Locking Tabelle entfernen sollte und die Zait ja auch irgendwann abgelaufen sein wird. Es könnte trotzdem mal zu unangenehmen Seiteneffekten kommen. Der Lock wird nämlich _mit_ release-Lock89 schon entfernt, wenn die beiden Operationen getätigt wurden und nicht erst, wenn die Zeit abgelaufen ist. Wenn Dein Script nun nach dem INSERT noch ein bisschen was anderes zu tun hat, dann hast Du wenigstens schon vorher die Bahn wieder freigemacht.
Die Doppeleintragungen kannst Du nur Datantechnisch abfangen. Gib deinem Eintragungsformular beim Aufruf eine eindeutige ID mit und trag die auch in die Tabelle ein. Leg auf das Feld einen unique Index. Dann verhindert mysql automatisch den doppelten Eintrag.
Grüße
Tom
besten dank für die hilfe. mir ist einfach nicht ganz klar, weshalb ich beim ausführen des folgenden skripts nur Resource id #2 erhalte, und nicht 1 oder 0.
$sql = 'select get_lock("50073",1)';
$res = mysql_query($sql);
echo $res;
gruss
peter
leider erhalte ich folgende fehlermeldung:
You have an error in your SQL syntax near 'get_lock ("name",1000)' at line 1
ich habe auch versucht einen anderen namen zu geben, aber ohne erfolg.
peter