Answers:
信号量表是由Drupal默认实现的锁定机制使用的。它与编程中常见的锁定机制没有什么不同:值用于验证操作已在进行中,以避免冲突或竞争状况。区别在于,通常,锁是一个文件,而Drupal使用数据库中的行。
实际上,锁定机构具有获取锁(lock_acquire()
)或等待锁释放(lock_wait()
)的功能。在这两种情况下,均使用信号量数据库。
// 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;
在Drupal中,不同的用户可以请求相同的页面,这意味着不同的线程或进程可以同时执行相同的代码。例如,在代码更新数据库表时,这可能会导致问题。使用锁是避免这种情况可能导致问题的一种方法。
使用数据库表的原因仅仅是因为Drupal需要数据库引擎才能工作。将数据库表也用于锁定机制是降低需求的一种方法。锁定机制也可以使用APCu扩展来实现,如果我没记错的话,有一个模块可以这样做。
@kiamlaluno的回答是完整而完美的。但是,我认为它着重于(出色地)使用drupal的信号量说明db锁定的概念/用法。
反过来,我会冒险接近OP:
信号量表的用途是(如信号量表创建描述中所述):
用于保存不能存储为Drupal变量的信号量,锁,标志等的表,因为它们不能被缓存。
因此,该表的目的不仅仅是数据库锁定机制(到目前为止,我可以从该注释中了解到),并且它还解决了避免缓存变量的技术要求。
注意:如果我弄错了,很高兴被对此主题有更多专业知识的人纠正。干杯!