回答:
セマフォテーブルは、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変数として格納できないセマフォ、ロック、フラグなどを保持するテーブル。
したがって、そのテーブルの目的は単なるdbロックメカニズムではなく(これまでのところ、そのコメントから理解できます)、変数のキャッシュを回避するという技術的な要件にも対応しています。
注意:私がこれを間違えた場合、このトピックについてより専門的な知識を持つ誰かによって修正されて喜んでいます。乾杯!