Yanıtlar:
Semafor tablosu, varsayılan olarak Drupal'dan uygulanan kilitleme mekanizmasından kullanılır . Programlamada görülen normal kilitleme mekanizmasından farklı değildir: Çatışma veya yarış koşullarından kaçınmak için bir işlemin devam ettiğini doğrulamak için bir değer kullanılır . Fark, normalde kilit bir dosyadır, Drupal ise bir veritabanındaki satırı kullanır.
Aslında, kilitleme mekanizması bir kilit ( lock_acquire()
) almak veya bir kilidin serbest bırakılmasını beklemek ( ) işlevlerine sahiptir lock_wait()
. Her iki durumda da semafor veritabanı kullanılır.
// 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'da, farklı kullanıcılar aynı sayfayı isteyebilir, bu da farklı iş parçacıklarının veya işlemlerin aynı kodu aynı anda yürütebileceği anlamına gelir. Kod, örneğin bir veritabanı tablosunu güncelleştirirken bu sorunlara neden olabilir. Kilitleri kullanmak, sorunlara neden olabilmenin bir yoludur.
Bir veritabanı tablosunun kullanılmasının nedeni, Drupal'ın çalışması için bir veritabanı motoru gerektirmesidir; kilitleme mekanizması için de bir veritabanı tablosu kullanmak gereksinimleri azaltmak için bir yoldur. Kilitleme mekanizması APCu uzantısı kullanılarak da uygulanabilir ve doğru hatırlarsam, bunu yapan bir modül vardır.
@Kiamlaluno'nun cevabı tam ve mükemmel. Ancak, dbal semaforlarını kullanarak db kilitleme kavramını / kullanımını (parlak bir şekilde) açıklamaya odaklandığını düşünüyorum.
Ben de girişim OP yaklaşıyor:
Semafor tablosunun amacı (semafor tablosu oluşturma açıklamasında açıklandığı gibi):
Önbelleklenmemesi gerektiğinden Drupal değişkenleri olarak saklanamayan semafor, kilit, bayrak vb. Tutma tablosu.
Yani, bu tablonun amacı sadece db kilitleme mekanizmaları daha fazla (şimdiye kadar bu yorumdan anlayabiliyorum), ve aynı zamanda değişkenlerin önbelleğe kaçınmak teknik gereksinimi ele.
DİKKAT: Eğer yanlış yaparsam, bu konuda daha fazla uzmanlığa sahip biri tarafından düzeltilmekten mutluluk duyarız. Şerefe!