Antworten:
Die Semaphor - Tabelle wird von dem verwendeten Arretiermechanismus standardmäßig aus Drupal umgesetzt. Es unterscheidet sich nicht von dem in der Programmierung üblichen Sperrmechanismus: Ein Wert wird verwendet, um zu überprüfen, ob eine Operation bereits ausgeführt wird, um Konflikte oder Rennbedingungen zu vermeiden. Der Unterschied besteht darin, dass die Sperre normalerweise eine Datei ist, während Drupal die Zeile in einer Datenbank verwendet.
Tatsächlich hat der Verriegelungsmechanismus Funktionen, um eine Sperre zu erhalten ( lock_acquire()
) oder zu warten, bis eine Sperre aufgehoben wird ( lock_wait()
). In beiden Fällen wird die Semaphor-Datenbank verwendet.
// lock_acquire()
// Optimistically try to acquire the lock, then retry once if it fails.
// The first time through the loop cannot be a retry.
$retry = FALSE;
// We always want to do this code at least once.
do {
try {
db_insert('semaphore')
->fields(array(
'name' => $name,
'value' => _lock_id(),
'expire' => $expire,
))
->execute();
// We track all acquired locks in the global variable.
$locks[$name] = TRUE;
// We never need to try again.
$retry = FALSE;
}
catch (PDOException $e) {
// Suppress the error. If this is our first pass through the loop,
// then $retry is FALSE. In this case, the insert must have failed
// meaning some other request acquired the lock but did not release it.
// We decide whether to retry by checking lock_may_be_available()
// Since this will break the lock in case it is expired.
$retry = $retry ? FALSE : lock_may_be_available($name);
}
//lock_may_be_available()
$lock = db_query('SELECT expire, value FROM {semaphore} WHERE name = :name', array(':name' => $name))->fetchAssoc();
if (!$lock) {
return TRUE;
}
$expire = (float) $lock['expire'];
$now = microtime(TRUE);
if ($now > $expire) {
// We check two conditions to prevent a race condition where another
// request acquired the lock and set a new expire time. We add a small
// number to $expire to avoid errors with float to string conversion.
return (bool) db_delete('semaphore')
->condition('name', $name)
->condition('value', $lock['value'])
->condition('expire', 0.0001 + $expire, '<=')
->execute();
}
return FALSE;
In Drupal können verschiedene Benutzer dieselbe Seite anfordern, was bedeutet, dass verschiedene Threads oder Prozesse denselben Code gleichzeitig ausführen können. Dies kann zu Problemen führen, wenn der Code beispielsweise eine Datenbanktabelle aktualisiert. Die Verwendung von Schlössern ist ein Weg, um dies zu vermeiden und Probleme zu verursachen.
Der Grund, warum eine Datenbanktabelle verwendet wird, ist einfach, dass Drupal ein Datenbankmodul benötigt, um zu funktionieren. Die Verwendung einer Datenbanktabelle auch für den Sperrmechanismus ist eine Möglichkeit, die Anforderungen zu reduzieren. Der Verriegelungsmechanismus könnte auch mit der APCu-Erweiterung implementiert werden, und wenn ich mich richtig erinnere, gibt es ein Modul, das dies tut.
Die Antwort von @kiamlaluno ist vollständig und perfekt. Aber ich denke, es konzentriert sich darauf, das Konzept / die Verwendung von DB-Locking unter Verwendung von Drupals Semaphoren (brillant) zu erklären.
Ich würde es wiederum wagen, näher an das OP heranzukommen:
Der Zweck der Semaphortabelle ist (wie in der Beschreibung zur Erstellung der Semaphortabelle beschrieben):
Tabelle zum Speichern von Semaphoren, Sperren, Flags usw., die nicht als Drupal-Variablen gespeichert werden können, da sie nicht zwischengespeichert werden dürfen.
Der Zweck dieser Tabelle ist also mehr als nur DB-Sperrmechanismen (soweit ich aus diesem Kommentar verstehen kann), und sie befasst sich auch mit der technischen Anforderung, das Zwischenspeichern von Variablen zu vermeiden.
NB: Ich werde mich freuen, von jemandem mit mehr Fachwissen zu diesem Thema korrigiert zu werden, wenn ich das falsch verstanden habe. Prost!