php.de

Zurück   php.de > Webentwicklung > Datenbanken

Datenbanken SQL und Co

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 09.02.2010, 16:10  
Neuer Benutzer
 
Registriert seit: 22.01.2010
Beiträge: 25
PHP-Kenntnisse:
Fortgeschritten
Samhayne befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von nikosch Beitrag anzeigen
Irgendwie ist mir das alles zu allgemein. Aber machs doch so:
1) wie gehabt. Beachte dabei nachfolgendes
2) Suche Dir eine ID, die Du bearbeiten willst. Setze auf diese ID (DB Update) einen Zeitstempel, der mindestens so weit in der Zukunft liegt, wie die Berechnung dauert. Datensätze mit nicht abgelaufenen Zeitstempeln werden vom Select in 1) ignoriert
3) wie gehabt.
4) wie gehabt. Lösche den Zeitstempel, bei Bedarf.
Nur Teilbereiche zu sperren wäre denkbar, wenn ich's mir recht überlege.
*grübel*
Ich wollt erst mal aber wirklich nur ein stupides Lock auf die ganze Tabelle.

Je nachdem müssen 10-50% der Tabelle verfügbar sein.

Jedoch kommt mir der Timeout auf jeden Eintrag arg unsicher vor.

Dauert's doch länger (Server hängt kurz?) wird abgebrochen und ich muss alles auffangen. (Und selbst feststellen, daß ich zu lang gebraucht hab und andere User nun anfangen drüberzuschreiben)

Dauert's weniger lang, müssen andere User unnötig warten.




Zitat:
Zitat von thomas_w Beitrag anzeigen
Noch ein paar Fragen für mein Verständnis:

a) Was soll mit den "wartenden" Usern in der Zeit passieren, solange der "LOCK" User die Daten ändert?

=> 1) die Skripte der "wartenden" User bleiben hängen und warten bis der LOCK gelöst ist => eventuelles TIMEOUT Problem
=> 2) die Skripte der "wartenden" User laufen weiter und lesen "alte" Daten
1) [X]


Zitat:
b) Wird vom dem "LOCK" User die gesamte Tabelle gesperrt oder nur einzelne Datensätze, -bereiche (von bis Postleitzeit z.B.)
Wie gesagt, wollt ich erst mal wirklich ganz stumpf die ganze Tabelle sperren.
Nur Teilbereiche zu sperren, würd' ich mir lieber erst im nächsten Schritt überlegen.

Zitat:
Zitat von thomas_w Beitrag anzeigen
c) Wie lange dauert der Update des "LOCK" Users?

=> 1) wenige (Milli)-Sekunden
=> 2) mehr als 5 Sekunden
Kann ich Dir so genau grad gar nicht sagen, da ich die Updatefunktion seit 3 Tagen umschreibe, weil sie so eeelendig lahm war. (+60 Sekunden + Timeout)

Hab nun (abgesehen von einem "SELECT alles_was_ich_brauche ..." zu Beginn) alle Datenbankzugriffe rausgeschmissen und operiere nur noch auf einem Datenobjekt (blabla... interessiert keinen) ...
Bin momentan bei ca. 'ner halben Sekunde.

Es fehlt noch bissl Rumgerechne und anschließend das zurückschreiben auf die Datenbank. Wie lang das dauert, weiß ich noch nicht.
Hoffe, alles in wenige große Updatestrings mit CASE Anweisungen verpacken zu können.


Zitat:
d) Wie häufig erfolgt so ein Update des "LOCK" Users?

=> 1) einmal pro Stunde
=> 2) sehr häufig
=> 3) sehr selten
Großes Update (ich rechne momentan mit allem zwischen 1 und 10 Sekunden) : Frühestens jede viertel Stunde.
Kleine Updates: (alle 15min) : wenige Millisekunden.








Um's doch mal ein wenig konkreter zu machen,

Das ganze is für'n Browserspiel mit dem ich mich bewerben will.

Die Tabelle ist eine Zeittabelle über drei Tage.
Jeder Spieler hat darin also bis zu 3*24 Einträge in dieser Tabelle in dem seine
geplanten "Aktionen" gespeichert werden.

Führt der Spieler ein Update durch, können dabei aber auch Einträge der Konkurrenz benötigt werden. (Was hat der und der zu dem Zeitpunkt gemacht?) Deren Aktionen werden dann auch gleich ausgewertet und anschließend die Zeittabellen bei Bedarf (teilweise) geleert und in die aktuelle Spielzeit verschoben (eingetragene, abgelaufene Aktionen vergangenere Tage gelöscht, Datum neu gesetzt).


Obendrein gibt's noch 2 weitere Tabellen mit Daten, von denen einzelne Einträge aktualisiert werden müssen, wenn die Zeittabelle abgearbeitet wird. Hier sollte es aber nicht zu Problemen kommen dürfen, wenn ich's halbwegs schlau angehe.

Funktioniert auch schon alles.

Dumm wird's nur, wenn zwei Spieler gleichzeitig auf der Tabelle zu aktualisieren beginnen.

Ich hoff', das macht nun nicht alles wirrer und wir kommen vom Hölzchen auf's Stöckchen. Wollt ich eigentlich vermeiden und es drum lieber bissl abstrakt halten.

Geändert von Samhayne (09.02.2010 um 16:45 Uhr).
Samhayne ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 09.02.2010, 17:24  
Erfahrener Benutzer
 
Registriert seit: 26.07.2006
Beiträge: 121
JumperII
Standard

Hallo,

langsam frage ich mich, ob Du hier nicht eher ein Konzeptproblem hast. Nach Deinen Schilderungen bislang habe ich hier scheinbar ein zweistufiges Problem. 1. Du möchtest z.Tl. umfangreiche Änderungen durchführen, die viel Zeit erfordern und erst nach Abschluss sichtbar sein dürfen. Unklar ist, erfolgen sie zyklisch automatisiert (was durchaus bei den angegebenen Zeiten sinnvoll wäre) oder interaktiv.
2. Du brauchst für die Anzeige immer eine valide Datenbasis die notfalls mit einer Anzeige versehen werden kann "wird gerade aktualisiert".

Mein Grundsatzvorschlag wäre dann, die Daten zur Neuberechnung neu in die Datenbank einzustellen und Alt- und Neu-datensätze durch eine ID oder einen Timestamp zu unterscheiden. Bis zur fertigstellung kann dann bei der Anzeige die altdaten gezogen werden, während für die neuen Daten sogar ein rollback möglich wäre. Die Existenz der Neudaten kann gleichzeitig als Indikator genommen werden, dass aktuell eine aktualisierung erfolgt.
Jetzt musst Du nur noch das Problem parallel zu bearbeitender Prozesse lösen. Hier kann eine vereinfachte semaphorenlösung genommen werden oder es werden die Änderungsdaten in einer separaten tabelle gesammelt und per batch/cron prozess dann aktualisiert.

das ganze kann natürlich noch optimiert werden.

Gruß
Jumper, the II.
JumperII ist offline   Mit Zitat antworten
Alt 09.02.2010, 17:31  
Erfahrener Benutzer
 
Registriert seit: 07.06.2008
Beiträge: 993
PHP-Kenntnisse:
Fortgeschritten
Frank befindet sich auf einem aufstrebenden Ast
Frank eine Nachricht über ICQ schicken Frank eine Nachricht über MSN schicken Frank eine Nachricht über Yahoo! schicken
Standard

Ich versteh' soweiso das ganze Problem nicht.

MySQL serialisiert deine Abfragen doch eh so, dass keine Konflikte entstehen. Dafür ist doch der Scheduler in MySQL sowieso verantwortlich und nunmal für genau diesen Zweck da.
__________________
Frank ist offline   Mit Zitat antworten
Alt 09.02.2010, 17:36  
Erfahrener Benutzer
 
Registriert seit: 26.07.2006
Beiträge: 121
JumperII
Standard

Zitat:
Zitat von Frank Beitrag anzeigen
Ich versteh' soweiso das ganze Problem nicht.

MySQL serialisiert deine Abfragen doch eh so, dass keine Konflikte entstehen. Dafür ist doch der Scheduler in MySQL sowieso verantwortlich und nunmal für genau diesen Zweck da.
Es geht nicht nur um ein transaktionssichers Schreiben sondern auch um eine konsistente Datensicht während der Transaktion. Im übrigen reicht die Serialisierung von mysql nicht aus, um alles sicher zu stellen, sonst hätten Locks und Transaktionen sich nie entwickelt

Gruß,
Jumper, the II.
JumperII ist offline   Mit Zitat antworten
Alt 09.02.2010, 19:23  
thomas_w
Gast
 
Beiträge: n/a
Standard

Um alles zu testen, brauchst Du eine mysql-console und ein php-skript. Damit simulierst Du die beiden parallelen konkurierenden Benutzer. Der Trick ist der SELECT .. FOR UPDATE. Damit reservierst Du Dir einen exklusiven Zugriff auf die Daten.

Code:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql>


mysql>SET AUTOCOMMIT = 0;

mysql>SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

mysql>SELECT * FROM tabelle FOR UPDATE;

-> jetzt ist die Tabelle gesperrt


mysql>UPDATE tabelle SET wert = 1;
mysql>COMMIT;

-> jetzt ist die Tabelle wieder frei
Das Thema ist leider nicht trivial und es gibt diverse Effekte, wenn die LOCKS nicht mehr richtig freigegeben werden. Vielleicht versuchst Du einen anderen Trick und zwar flock() mit einem Dummy-File.


PHP-Code:
  $fp fopen($file'a+');                   // Datei oeffnen 
   
  
if (flock($fpLOCK_EX)) {                  // exclusive lock 
    
$count fread($fpfilesize($file)) + 1// bisherigen Wert lesen 
    
ftruncate($fp0);                        // loeschen 
    
fwrite($fp$count);                      // neuen Wert schreiben 
    
flock($fpLOCK_UN);                      // release lock 
  
} else { 
    echo 
"Couldn't get the lock!"
  } 
Wer den LOCK_EX korrekt erhält, darf in der Datenbank arbeiten...

Grüße
Thomas
  Mit Zitat antworten
Alt 09.02.2010, 20:09  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 34.241
PHP-Kenntnisse:
Fortgeschritten
nikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz sein
Standard

Ich finde die Diskussion geht viel zu weit in die Richtung Locking, obwohl das gar nicht nötig zu sein scheint (ausser dass der TE das irgendwo gelesen und deshalb hier geschrieben hat). Spricht irgendwas gegen meinen Vorschlag aus #19 (LOCK tables...)?
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 09.02.2010, 21:00  
Erfahrener Benutzer
 
Registriert seit: 26.07.2006
Beiträge: 121
JumperII
Standard

solange nicht geklärt ist, was und wie etwas zu welchen zeitpunkten gesperrt, mit altenn daten oder zeitaktuell abgefragt werden kann, darf und muss, kann keine optimale lösung diskutiert werden. Ich persönlich sehe bei den bislang beschriebenen Anforderungen eigentlich eher den Bedarf an einer sinnvollen Analyse, bei der die Verarbeitungsstrategie geprüft und ggf. revidiert werden sollte.
Locks uns semaphoren können sinnvoll sein, sind aber als potentielle störer der verarbeitung in ihren Einsatz auf das absolut notwendige Minimum zu reduzieren.

An dieser Stelle ist aber der Anfragende gefragt und nicht wir

Gruß,
Jumper, the II.
JumperII ist offline   Mit Zitat antworten
Alt 09.02.2010, 21:30  
erc
Erfahrener Benutzer
 
Registriert seit: 02.01.2009
Beiträge: 730
PHP-Kenntnisse:
Fortgeschritten
erc wird schon bald berühmt werden
Standard

Es ist schon interessant wieviele Posts man machen kann trotz das die Lösung schon im Titel steht! Ein write lock macht genau das was gefordert ist, sobald ein Thread ein write lock hat kann kein anderer Thread mehr die Tabelle lesen noch schreiben. Alternativ bringt Mysql auch get_lock() als pseudo lock mit (was hier versucht wird nach zu bauen). Hat den Vorteil man kann selbst entscheiden wer diesen Lock berücksichtigen soll. Würde aber ein write lock vorziehen wenn ich nur schnell ein paar Datensätze einfügen will, ist performance technisch von Vorteil.
erc ist offline   Mit Zitat antworten
Alt 09.02.2010, 21:56  
Neuer Benutzer
 
Registriert seit: 22.01.2010
Beiträge: 25
PHP-Kenntnisse:
Fortgeschritten
Samhayne befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von thomas_w Beitrag anzeigen
Um alles zu testen, brauchst Du eine mysql-console und ein php-skript. Damit simulierst Du die beiden parallelen konkurierenden Benutzer. Der Trick ist der SELECT .. FOR UPDATE. Damit reservierst Du Dir einen exklusiven Zugriff auf die Daten.
Danke, Thomas.
Durch das SELECT ... FOR UPDATE werden die Reihen also gesperrt!

Hab's getestet.

Browser bringt 60 Sekunden Sanduhr und schmeißt einem dann ein
"Lock wait timeout exceeded; try restarting transaction."
entgegen.

Ausser zwischendurch kommt das COMMIT oder ich beende mysql.exe mit exit;.
Dann ist die Sanduhr sofort weg und die Seite lädt.

Das wär ja eigentlich genau das, was ich suche.

Is nur die Frage, was passiert, wenn was unerwartetes passiert und noch ein Lock gesetzt ist.
Hm. Ich schätz' mal, nach dem inactivity connection timeout des clients würde auch das lock aufgehoben?

Der Standardwert liegt bei 60 Sekunden, kann das sein?

Wär' ja nicht schlimm, wenn im Worst Case das Ding mal 60 Sekunden ausfällt...


Die Anweisungen kann ich auch in php mysql(i)_query()s packen und es funktioniert noch?








Zitat:
Zitat von thomas_w Beitrag anzeigen
Das Thema ist leider nicht trivial und es gibt diverse Effekte, wenn die LOCKS nicht mehr richtig freigegeben werden. Vielleicht versuchst Du einen anderen Trick und zwar flock() mit einem Dummy-File.


PHP-Code:
  $fp fopen($file'a+');                   // Datei oeffnen 
   
  
if (flock($fpLOCK_EX)) {                  // exclusive lock 
    
$count fread($fpfilesize($file)) + 1// bisherigen Wert lesen 
    
ftruncate($fp0);                        // loeschen 
    
fwrite($fp$count);                      // neuen Wert schreiben 
    
flock($fpLOCK_UN);                      // release lock 
  
} else { 
    echo 
"Couldn't get the lock!"
  } 
Wer den LOCK_EX korrekt erhält, darf in der Datenbank arbeiten...

Grüße
Thomas
Der Trick ist gleich so raffiniert... den kapier ich gleich gar nicht.
Grundidee ist klar... Lock über ein File auf der Platte.
Aber was wird da erhöht und gezählt... und warum wird es erhöht?


Zitat:
Zitat von JumperII Beitrag anzeigen
Hallo,

langsam frage ich mich, ob Du hier nicht eher ein Konzeptproblem hast. Nach Deinen Schilderungen bislang habe ich hier scheinbar ein zweistufiges Problem. 1. Du möchtest z.Tl. umfangreiche Änderungen durchführen, die viel Zeit erfordern und erst nach Abschluss sichtbar sein dürfen. Unklar ist, erfolgen sie zyklisch automatisiert (was durchaus bei den angegebenen Zeiten sinnvoll wäre) oder interaktiv.
2. Du brauchst für die Anzeige immer eine valide Datenbasis die notfalls mit einer Anzeige versehen werden kann "wird gerade aktualisiert".
Die Aktualisierung erfolgt interaktiv.
Wenn 4 Tage nix passiert, passiert auch nix.
Der erste Spieler, der sich einlogged stösst dann ein Update für alle Spieler an, mit denen er was zu tun.

Ich bastel nicht erst seit gestern daran, drum wirst zu sicher mein Sträuben verstehen, nochmal all zu viel dran umzumodeln.

Bei der Aktualisierung die Dateien neu zu schreiben hab ich bewusst vermieden um die Einträge der Spieler nicht quer über die Datenbank zu verteilen. (Klar kann man's durch einen passenden Select wieder ordnen, wenn man reinguckt, aber... mir gefiel's besser, daß IDmässig Spieler kompakt auf Spieler folgt)

Mein letztes Problem ist eben das Locking der Tabelle, so daß die User sich nicht in die Quere kommen, wenn sie darauf schreiben.

Geändert von Samhayne (09.02.2010 um 22:02 Uhr).
Samhayne ist offline   Mit Zitat antworten
Alt 09.02.2010, 22:29  
Neuer Benutzer
 
Registriert seit: 22.01.2010
Beiträge: 25
PHP-Kenntnisse:
Fortgeschritten
Samhayne befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von erc Beitrag anzeigen
Es ist schon interessant wieviele Posts man machen kann trotz das die Lösung schon im Titel steht! Ein write lock macht genau das was gefordert ist, sobald ein Thread ein write lock hat kann kein anderer Thread mehr die Tabelle lesen noch schreiben. Alternativ bringt Mysql auch get_lock() als pseudo lock mit (was hier versucht wird nach zu bauen). Hat den Vorteil man kann selbst entscheiden wer diesen Lock berücksichtigen soll. Würde aber ein write lock vorziehen wenn ich nur schnell ein paar Datensätze einfügen will, ist performance technisch von Vorteil.
Ich find' das Thema aber auch wirklich etwas verwirrend....

Dachte, sowas sei derart täglich Brot, daß es 'ne schnöde Standardantwort geben müsste.
Aber schon beim Durchblättern der Bücher wurd's da irgendwie... recht konfus.


get_lock() hab ich mir heut morgen sogar angeglotzt... aber nicht gleich kapiert und mir eingebildet, daß ich eh was anderes such...


Auch sehr schick eigentlich...

PHP-Code:

$sql 
"SELECT GET_LOCK('lock1',10)";

$result mysqli_query($db1$sql) or die ("MySQL lock error: " mysqli_error($db1));

$row mysqli_fetch_row($result);
echo 
"db1 user trying to lock... result: $row[0] <br />";

$result mysqli_query($db2$sql) or die ("MySQL lock error: " mysqli_error($db2));

$row mysqli_fetch_row($result);
echo 
"db2 user trying to lock... result: $row[0] <br />"
Gibt aus:
Code:
db1 user trying to lock... result: 1 
[10 Sekunden Pause]
db2 user trying to lock... result: 0

Ein Parameter für das Timeout des Locks wär schicker gewesen als ein Parameter wann der User 'nen Timeout kriegt.

Aber auch hier wird hoffentlich dasselbe gelten und das Lock auf jeden Fall nach 60 Sekunden gelöst werden.

edit:
Hmm... naja... mal auf 70 Sekunden hochgestellt, den lock timeout, und zwischen den ersten und den zweiten Query ein sleep(30) gebastelt:

Code:
Warning: mysqli_query() [function.mysqli-query]: MySQL server has gone away in C:\_web\myserver.dev\public_html\...
on line 212

Warning: mysqli_query() [function.mysqli-query]: Error reading result set's header in C:\_web\myserver.dev\public_html\...
on line 212

Fatal error: Maximum execution time of 60 seconds exceeded in C:\_web\myserver.dev\public_html\...\_locktest.php on line 212
Scheint mir aber trotzdem grad die billigste Lösung zu sein, die mir am wenigsten "Tut das wirklich?" Bauchschmerzen macht.

Geändert von Samhayne (09.02.2010 um 22:51 Uhr).
Samhayne ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Erledigt] mysql_insert_id () und LOCK TABLES Senifor PHP Tipps 2009 2 29.10.2009 15:40
[Erledigt] breadcrumb 2 Tables mit Subcategories fulltilt PHP Tipps 2009 6 19.09.2009 07:57
Kann LOCK TABLES zu Absturz der MySQL Datenbank führen? kat_2403 Datenbanken 2 03.09.2009 15:22
mysqlabfrage mit 2 tables (COUNT?) mqs PHP Tipps 2009 6 17.06.2009 12:49
Welche Tables muss ich erstellen? She-Sign.de Datenbanken 2 12.05.2009 19:54
[Erledigt] LOCK TABLES - Thread statt Table??? Curanai Datenbanken 1 04.04.2009 01:33
[Erledigt] Problem bei delete über 2 tables fulltilt PHP Tipps 2009 3 24.02.2009 22:29
Impossible WHERE noticed after reading const tables Gumfuzi Datenbanken 6 03.01.2009 10:53
Extrahieren aus 2 Tables mit einem bekannten Wert ssm Datenbanken 12 23.03.2006 20:29
Tables Schubi PHP Tipps 2005-2 0 05.08.2005 15:09
Tables Schubi PHP Tipps 2005-2 0 05.08.2005 15:08
Tables PHP Tipps 2005-2 0 05.08.2005 13:39
LOCK TABLES / LAST_INSERT_ID AliceD Datenbanken 3 20.07.2005 13:45
Suche zufalls(bild)script das in tables läuft... Beitragsarchiv 0 05.07.2005 12:18
SHOW PROCESSLIST und TEMPORARY TABLES tapferesschneiderlein Datenbanken 2 05.03.2005 11:40

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
mysql get_lock lock tables, mysql nach update daten gesperrt, php flock timeout, mysql get_lock, php locking, tabellen lock mysql grund ermitteln, php script trotz fehler weiter ausführen, db2 row nach select sperren, tutow postleitzeit, select for update db2, mysql table_lock_wait, mysql lock wait timeout exceeded, lock wait timeout exceeded try restarting transaction, vielleicht gibt es noch eine abgelaufene lock-datei, php db2 exclusive lock, mysqli lock table write, vielleicht gibt es noch eine abgelaufene lock-datei?, table lock php get_lock(), select \for update\ db2, commit zwischendurch bei umfangreichen update

Alle Zeitangaben in WEZ +1. Es ist jetzt 02:06 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum