一般而言,Drupal DB信号量表的目的是什么


9

我了解IPC编程中信号量的目的,但是我没有找到关于此表目的的很好的解释。

Answers:


11

信号量表是由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扩展来实现,如果我没记错的话,有一个模块可以这样做。


极好的答案。但是,为了清楚起见,信号量表与数据库引擎自身的本地锁定机制(例如mysql)是分开的。
迈克

2
信号量表由Drupal创建和使用。数据库引擎未使用它。
kiamlaluno

6

@kiamlaluno的回答是完整而完美的。但是,我认为它着重于(出色地)使用drupal的信号量说明db锁定的概念/用法。

反过来,我会冒险接近OP:

信号量表的用途是(如信号量表创建描述中所述):

用于保存不能存储为Drupal变量的信号量,锁,标志等的表,因为它们不能被缓存。

因此,该表的目的不仅仅是数据库锁定机制(到目前为止,我可以从该注释中了解到),并且它还解决了避免缓存变量的技术要求。

注意:如果我弄错了,很高兴被对此主题有更多专业知识的人纠正。干杯!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.