Respuestas:
La tabla de semáforos se utiliza desde el mecanismo de bloqueo implementado por defecto desde Drupal. No es diferente del mecanismo habitual de bloqueo visto en la programación: se utiliza un valor para verificar que una operación ya está en progreso, para evitar conflictos o condiciones de carrera. La diferencia es que, normalmente, el bloqueo es un archivo, mientras que Drupal usa la fila en una base de datos.
De hecho, el mecanismo de bloqueo tiene funciones para adquirir un bloqueo ( lock_acquire()
), o esperar a que se libere un bloqueo ( lock_wait()
). En ambos casos, se utiliza la base de datos de semáforos.
// 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;
En Drupal, diferentes usuarios pueden solicitar la misma página, lo que significa que diferentes hilos o procesos podrían ejecutar el mismo código al mismo tiempo. Esto podría causar problemas cuando el código está, por ejemplo, actualizando una tabla de base de datos. El uso de bloqueos es una forma de evitar que esto pueda causar problemas.
La razón por la que se usa una tabla de base de datos es simplemente que Drupal requiere un motor de base de datos para funcionar; El uso de una tabla de base de datos también para el mecanismo de bloqueo es una forma de reducir los requisitos. El mecanismo de bloqueo también podría implementarse utilizando la extensión APCu, y si recuerdo correctamente, hay un módulo que lo hace.
La respuesta de @kiamlaluno es completa y perfecta. Pero, creo que se centra en explicar (brillantemente) el concepto / uso del bloqueo de db usando los semáforos de drupal.
A su vez, me aventuraría a acercarme al OP:
El propósito de la tabla de semáforos es (como se describe en la descripción de la creación de la tabla de semáforos):
Tabla para contener semáforos, bloqueos, banderas, etc. que no pueden almacenarse como variables de Drupal ya que no deben almacenarse en caché.
Entonces, el propósito de esa tabla es más que solo mecanismos de bloqueo de db (hasta ahora puedo entender de ese comentario), y también aborda el requisito técnico de evitar el almacenamiento en caché de variables.
NB: Estaré encantado de ser corregido por alguien con más experiencia en este tema si me equivoco. ¡Salud!