Réponses:
La table sémaphore est utilisée à partir du mécanisme de verrouillage implémenté par défaut à partir de Drupal. Il n'est pas différent du mécanisme de verrouillage habituel vu en programmation: une valeur est utilisée pour vérifier qu'une opération est déjà en cours, pour éviter les conflits ou les conditions de concurrence. La différence est que, normalement, le verrou est un fichier, tandis que Drupal utilise la ligne dans une base de données.
En fait, le mécanisme de verrouillage a des fonctions pour acquérir un verrou ( lock_acquire()
), ou attendre qu'un verrou soit libéré ( lock_wait()
). Dans les deux cas, la base de données des sémaphores est utilisée.
// 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;
Dans Drupal, différents utilisateurs peuvent demander la même page, ce qui signifie que différents threads ou processus peuvent exécuter le même code en même temps. Cela peut provoquer des problèmes lorsque le code met, par exemple, à jour une table de base de données. L'utilisation de verrous est un moyen d'éviter que cela ne cause des problèmes.
La raison pour laquelle une table de base de données est utilisée est simplement que Drupal nécessite un moteur de base de données pour fonctionner; l'utilisation d'une table de base de données également pour le mécanisme de verrouillage est un moyen de réduire les exigences. Le mécanisme de verrouillage pourrait également être implémenté en utilisant l'extension APCu, et si je me souviens bien, il y a un module qui le fait.
La réponse de @kiamlaluno est complète et parfaite. Mais, je pense qu'il se concentre sur l'explication (brillante) du concept / de l'utilisation du verrouillage db en utilisant les sémaphores de drupal.
Je me risquerais à mon tour à me rapprocher du PO:
Le but de la table sémaphore est (comme décrit dans la description de la création de la table sémaphore):
Tableau de stockage des sémaphores, verrous, drapeaux, etc. qui ne peuvent pas être stockés en tant que variables Drupal car ils ne doivent pas être mis en cache.
Ainsi, le but de ce tableau est plus que des mécanismes de verrouillage db (jusqu'à présent, je peux comprendre ce commentaire), et il répond également à l'exigence technique d'éviter la mise en cache des variables.
NB: Sera heureux d'être corrigé par quelqu'un avec plus d'expertise sur ce sujet si je me trompe. À votre santé!