Was willst du denn mit dem LOCK erreichen? Dass der andere garnicht ausgeführt wird, oder?
Schick mal den ganzen Query, die bloßen DB-Namen sind ja wohl kaum geheim.
Probier eventuell mal die shm- und sem-Funktionen.
Edit:
Ich habe jetzt noch einmal nachgeschaut:
LOCK TABLE wirkt quasi wie ein Semaphore: Das Script, das zu spät kommt, muss warten, bis das andere fertig ist, die Aktion wird dennoch durchgeführt.
Ich schreib mal was kleines:
class LockException extends Exception
{
public $data;
public function __construct($message, $data = null)
{
parent::__construct($message);
$this->data = $data;
}
}
class Lock
{
protected static $shmid = 7621461;
public static function tryIt($transactionid, $datafunc = null)
{
$c = shm_attach(self::$shmid);
$s = sem_get(self::$shmid);
sem_acquire($s);
$v = @shm_get_var($c, $transactionid);
sem_release($s);
if($v !== false)
throw new LockException('It is locked', $v);
sem_acquire($s);
$data = is_callable($datafunc) ? call_user_func($datafunc, $transactionid) : $datafunc;
shm_put_var($c, $transactionid, $data);
sem_release($s);
sem_remove($s);
shm_detach($c);
return $data;
}
public static function releaseIt($transactionid)
{
$c = shm_attach(self::$shmid);
$s = sem_get(self::$shmid);
sem_acquire($s);
$result = @shm_remove_var($c, $transactionid);
sem_release($s);
sem_remove($s);
shm_detach($c);
}
}
Alles anzeigen
Alternativ kannst du aus $c (connection) und $s (semaphore) auch statische Klassenmember machen oder das Ganze nicht statisch aufziehen. So kannst dus dann anwenden, du brauchst eben ne Transaction-ID:
$transactionid = ermittleDatenSatzDerNichtDoppeltEingefügtWerdenDarf();
function erzeugeDatenSatz($id)
{
// Aus DB lesen...
}
try
{
$data = Lock::tryIt($transactionid, 'erzeugeDatenSatz');
fügeEin($data);
Lock::releaseIt($transactionid);
}
catch(LockException $e)
{
// Daten wurden schon eingefügt
// $e->data kann nun verwendet werden
$data = $e->data;
}
// Nun kann $data verwendet werden, egal ob es vom Thread neu eingefügt wurde oder ein anderer Thread zuvorgekommen ist
Alles anzeigen
Die Daten werden hierbei nur erzeugt, wenn nicht gelockt wurde. Wenn die Daten in jedem Thread einzeln erzeugt werden sollen, sieht es so aus:
$transactionid = ermittleDatenSatzDerNichtDoppeltEingefügtWerdenDarf();
$data = erzeugeDatenSatz($transactionid);
try
{
Lock::tryIt($transactionid, $data);
fügeEin($data);
Lock::releaseIt($transactionid);
}
catch(LockException $e)
{
// $data ist sowieso schon gesetzt
}
// $data kann verwendet werden
Alles anzeigen
Hierbei muss nicht mehr zwingend eine Funktion zur Datensatzerzeugung erstellt werden, dafür macht jeder Thread sein eigenes Ding.
Hinweise:
Das ganze funktioniert nicht unter Windoof.
$transactionid muss ein Integer sein.
$data kann eine beliebige Variable sein. (Objekt, Array,..., bloß keine Ressource oder boolesches false)
Viele liebe Grüße
The User
Edit:
Ich habe es jetzt getestet und es geht.
Wer es probieren möchte, öffnet einfach 2-3mal dieses Script:
<?
header('content-type: text/html; charset=utf-8');
require_once 'lock.php';
$transactionid = 150;
function erzeugeDatenSatz($id)
{
return rand() % $id;
}
try
{
$data = Lock::tryIt($transactionid, 'erzeugeDatenSatz');
sleep(10);
echo 'Eingefügt: ' . $data;
Lock::releaseIt($transactionid);
}
catch(LockException $e)
{
// Daten wurden schon eingefügt
// $e->data kann nun verwendet werden
echo 'Jemand anders war schneller';
$data = $e->data;
}
echo '<br/>Der Datensatz ist nun: ' . $data;
// Nun kann $data verwendet werden, egal ob es vom Thread neu eingefügt wurde oder ein anderer Thread zuvorgekommen ist
?>
Alles anzeigen
Und - oh Wunder - einer lockt und die anderen erhalten die selbe Zufallszahl.