MySQL ve PHP: Atomsallık ve iki sonraki sorguları yürütme bir PHP kod bloğunun yeniden entrancy - ne kadar tehlikeli?

0 Cevap php

MySQL ben bir kayıt eklemek değilse seçme sorgusu, herhangi bir kayıt geri döndü olup olmadığını kontrol etmelisiniz. Ben bütün PHP komut if-else işlemi ben istiyorum gibi atom DEĞİLDİR olduğunu, yani bazı senaryolarda kıracak olsa korkuyorum, örneğin aynı kayıt ile çalışmış olması gereken yerde senaryonun başka bir örneği denir ise:

if(select returns at least one record)
{
    update record;
}
else
{
    insert record;
}

Burada işlemler kullanmak vermedi, ve autocommit üzerinde. PHP 5.3 ile MySQL 5.1 kullanıyorum. Tablo InnoDB. Yukarıdaki kod suboptimaldir ve gerçekten kıracak eğer bilmek istiyorum. Ben aynı komut iki örnekleri tarafından yeniden girdi ve aşağıdaki sorgu dizisi gerçekleşir demek:

  1. Örneğin kayıt seçmek için 1 girişimleri, hiçbiri, insert sorgusu için blok girer bulur
  2. Örneğin kayıt seçmek için 2 girişimleri, hiçbiri, insert sorgusu için blok girer bulur
  3. kayıt eklemek için örnek 1 girişimleri, başarılı
  4. Örneğin bir kayıt eklemek için 2 girişimleri, başarısız, otomatik komut dosyasını iptal

O örneği 2 Anlamı ekleme sorgusu aşağıdaki ifadeyi şey atlama, bir hata iptal ve dönecektir. Ben hata ölümcül değil yapabilir, ama benim korkular burada gerçek olup olmadığını ben hataları görmezden sevmiyorum, ben daha ziyade bilemez.

Update: What I ended up doing (is this ok for SO?)

Bir daraltma içinde soru asist tablo uygulama her alıcıya gönderir iletilerinin miktarını (, inkar / gerçekten izin). Sistem aşağıdaki gibi tablo [kavramsal] bir süre Z. içinde bir alıcıya Y X mesajlardan daha fazla göndermek gerekir:

create table throttle
(
    recipient_id integer unsigned unique not null,
    send_count integer unsigned not null default 1,
    period_ts timestamp default current_timestamp,
    primary key (recipient_id)
) engine=InnoDB;

Ve tablodaki doğru verileri korur ve / gaz durumuna bağlı olarak mesaj gönderme yalanladı sağlayan bir atomik işlem yapmak gerekiyordu [biraz basitleştirilmiş / kavramsal] PHP kod bloğu:

function send_message_throttled($recipient_id) /// The 'Y' variable
{
    query('begin');

    query("select send_count, unix_timestamp(period_ts) from throttle where recipient_id = $recipient_id for update");

    $r = query_result_row();

    if($r)
    {
        if(time() >= $r[1] + 60 * 60 * 24) /// The numeric offset is the length of the period, the 'Z' variable
        {/// new period
            query("update throttle set send_count = 1, period_ts = current_timestamp where recipient_id = $recipient_id");
        }
        else
        {
            if($r[0] < 5) /// Amount of messages allowed per period, the 'X' variable
            {
                query("update throttle set send_count = send_count + 1 where recipient_id = $recipient_id");
            }
            else
            {
                trigger_error('Will not send message, throttled down.', E_USER_WARNING);
                query('rollback');
                return 1;
            }
        }
    }
    else
    {
        query("insert into throttle(recipient_id) values($recipient_id)");
    }

    if(failed(send_message($recipient_id)))
    {
        query('rollback');
        return 2;
    }

    query('commit');
}

Eh, InnoDB kilitlenmeleri ortaya çıktığı gerçeğini göz ardı ederek, bu hiçbir oldukça iyidir? Benim göğüs falan vurma değilim, ama bu sadece vs çünkü daha sık güncelleştirmeler / ekler MyISAM ile gidiyor ve ben yapmak istemiyorum tüm tabloyu, kilitleme kısa yapabilirim performans / istikrarın en iyi karışımı, seçer.

0 Cevap