Risposte:
La tabella dei semafori viene utilizzata dal meccanismo di blocco implementato di default da Drupal. Non è diverso dal solito meccanismo di blocco visto in programmazione: un valore viene utilizzato per verificare che un'operazione sia già in corso, per evitare conflitti o condizioni di gara. La differenza è che, normalmente, il blocco è un file, mentre Drupal utilizza la riga in un database.
In effetti, il meccanismo di blocco ha funzioni per acquisire un blocco ( lock_acquire()
) o attendere il rilascio di un blocco ( lock_wait()
). In entrambi i casi, viene utilizzato il database dei semafori.
// 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, diversi utenti possono richiedere la stessa pagina, il che significa che thread o processi diversi potrebbero eseguire lo stesso codice contemporaneamente. Ciò potrebbe causare problemi quando, ad esempio, il codice aggiorna una tabella del database. L'uso dei lucchetti è un modo per evitare che ciò possa causare problemi.
Il motivo per cui viene utilizzata una tabella di database è semplicemente che Drupal richiede un motore di database per funzionare; l'utilizzo di una tabella di database anche per il meccanismo di blocco è un modo per ridurre i requisiti. Il meccanismo di blocco potrebbe essere implementato anche usando l'estensione APCu, e se ricordo bene, c'è un modulo che lo fa.
La risposta di @kiamlaluno è completa e perfetta. Ma penso che si concentri sulla spiegazione (brillantemente) del concetto / uso del blocco db usando i semafori di Drupal.
Mi azzerei a mia volta avvicinandomi all'OP:
Lo scopo della tabella dei semafori è (come descritto nella descrizione della creazione della tabella dei semafori):
Tabella per contenere semafori, blocchi, flag, ecc. Che non possono essere memorizzati come variabili Drupal poiché non devono essere memorizzati nella cache.
Quindi, lo scopo di quella tabella è qualcosa di più dei semplici meccanismi di blocco dei db (finora posso capire da quel commento), e affronta anche il requisito tecnico di evitare la memorizzazione nella cache delle variabili.
NB: Sarò felice di essere corretto da qualcuno con maggiori competenze su questo argomento se ho sbagliato. Saluti!