Frage

Das Ziel ist einen PHP-Skript mit einem bestimmten Abschnitt des Codes zu haben, die nur von einem Thread / Prozess zu einem Zeitpunkt ausgeführt werden können.

Einige Einschränkungen:

  • Semaphore nicht auf meinem System
  • Das Handbuch erwähnt, dass die Herde () kann nicht auf in Multi-Threaded-Server verlassen, so flock () fehlt. (Bestätigt dies)

So dachte es möglich wäre, (warum nicht?) MySQL zu verwenden für die Synchronisation, aber ich bin immer zu unerwarteten Ergebnissen.

Zum Test habe ich öffnen zwei Browser-Tabs mit dem Skript test.php

mysql_connect($dbhost, $dbusername, $dbpassword); mysql_select_db($database_name);

$sql = "SELECT my_val FROM my_table WHERE my_var='status' "; $result = mysql_query($sql)or die(mysql_error()); $row = mysql_fetch_array($result, MYSQL_ASSOC); echo "status is:".$row['my_val']."
\n"; mysql_free_result($result);

if ($row['my_val']=='RUNNING') die ('process is already running!');

// entering critical section

$sql = "UPDATE my_table SET my_val='RUNNING' WHERE my_var='status' "; mysql_query ($sql);

sleep(10); // do some work here. echo 'finished work
';

// leave critical section. let the others know $sql = "UPDATE my_table SET my_val='NOT_RUNNING' WHERE my_var='status' "; mysql_query ($sql);

Die Tabelle ist:

CREATE TABLE `my_table` (
  `my_var` varchar(255) NOT NULL default '',
  `my_val` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`my_var`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `my_table`
VALUES (
'status', 'NOT_RUNNING'
) 

gehe ich in den ersten Browser-Tab und Zugriff auf das Skript. Ich warte 5 Sekunden, gehen Sie auf die anderen Registerkarte und den Zugang das Skript so, dass beiden Skripte parallel ausgeführt werden. Ich erwarte, dass der erste Reiter warten, und der zweite Registerkarte nach der ersten Abfrage beenden sollte. Jedoch warten die beiden Zungen am sleep () Linie. Dies bedeutet, dass die erste Abfrage immer gibt ‚NOT_RUNNING‘.

Einige seltsame Dinge:

  • Wenn ich das obige Experiment wiederholen, führen wir beiden Laschen in FireFox, und dann in einem dritten verschiedenen Browser-Typ, sagt Chrome, dann funktioniert es! (Status wird auf RUNNING während des Schlafes Script beendet früh, wenn der Status läuft)
  • Wenn ich das obige Experiment mit zwei verschiedenen Kommandozeilen-Fenstern wiederholen, und das Skript von der Kommandozeile ausgeführt werden, es funktioniert!
  • I phpMyAdmin überprüfen, während sie wartet, Status korrekt aktualisiert wird.

Ich habe alles versucht, die Tabellensperren, Transaktionen, SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED, SET autocommit = 1 ;, noch immer das gleiche Ergebnis.

Wer weiß, was hier geschieht? Gibt es eine gute Lösung für dieses Problem?

Systeme getestet: - Win, MySQL 5.0, PHP 5.3 - Linux, MySQL 5.0.91-community-log, PHP 5.2.12

Ich bin total steckte hier, vielen Dank für einen Blick!


UPDATE:

Vielen Dank für Ihre Antworten einreichen - ich kann immer noch dieses Problem nicht lösen. Hier ist der Code mit GET_LOCK () und session_write_close () wie vorgeschlagen: Ich habe auch auf Zeilenebene Verriegelungs, Transaktionen und verschiedene Isolationsstufen versucht. Vielleicht kann es nicht getan werden?

session_write_close();

mysql_connect($dbhost, $dbusername, $dbpassword);
mysql_select_db($database_name);

$sql = "CREATE TABLE IF NOT EXISTS `my_table`  (
  `my_var` varchar(255) NOT NULL default '',
  `my_val` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`my_var`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
";
mysql_query($sql)or die(mysql_error());

mysql_query ("SELECT get_lock('my_lock', 100)");

$sql = "SELECT my_val FROM `my_table` WHERE `my_var`='status' ";
$result = mysql_unbuffered_query($sql)or die(mysql_error());
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "status is:".$row['my_val']."
\n"; mysql_free_result($result); if ($row['my_val']=='RUNNING') die ('process is already running!'); // entering critical section $sql = "UPDATE `my_table` SET `my_val`='RUNNING' WHERE `my_var`='status' "; mysql_query ($sql); sleep(10); // do some work here. echo 'finished work
'; // leave critical section. let the others know //$sql = "UPDATE `my_table` SET `my_val`='NOT_RUNNING' WHERE `my_var`='status' "; $sql = "REPLACE INTO `my_table` (`my_var`,`my_val`) VALUES ('status', 'NOT_RUNNING')"; mysql_query ($sql); $result = mysql_query($sql)or die(mysql_error()); mysql_query ("SELECT release_lock('my_lock')"); die();
War es hilfreich?

Lösung

Der zweite Browserfenster hängt nicht auf dem sleep Befehl. Es ist blockiert, weil Sitzungen blockiert (und daher wird es versuchen, die gleiche Sitzung zu öffnen). Sie können die aktuelle Sitzung schließen, wenn Sie es nicht mehr benötigen (und daher wollen sie nicht zu Block) mit session_write_close ...

Andere Tipps

hat Mysql eine Funktion namens GET_LOCK .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top