2012-05-28 135 views
0

我有一個奇怪的bug,這裏涉及到mysql和php。我想知道它是否也是我們服務器的性能問題。快速插入導致數據丟失

我有一個班級用於管理回扣促銷代碼。代碼非常好,工作正常,而且完全沒有它應該做的。 saveChanges()操作根據對象的狀態發送INSERT或UPDATE,並且在當前上下文中將只插入原因,我試圖生成優惠券代碼。

該類的saveChanges是這樣的:(我知道,我不應該使用舊的mysql,但由於軟件的架構限制,我沒有選擇,所以請不要抱怨那部分)

public function saveChanges($asNew = false){ 

    //Get the connection 
    global $conn_panier; 

    //Check if the rebate still exists 
    if($this->isNew() || $asNew){ 

     //Check unicity if new 
     if(reset(mysql_fetch_assoc(mysql_query('SELECT COUNT(*) FROM panier_rabais_codes WHERE code_coupon = "'.mysql_real_escape_string($this->getCouponCode(), $conn_panier).'"', $conn_panier))) > 0){ 
      throw new Activis_Catalog_Models_Exceptions_ValidationException('Coupon code "'.$this->getCouponCode().'" already exists in the system', $this, __METHOD__, $this->getCouponCode()); 
     } 

     //Update the existing rebate 
     mysql_query($q = 'INSERT INTO panier_rabais_codes 
         (
          `no_rabais`, 
          `code_coupon`, 
          `utilisation`, 
          `date_verrou` 
         )VALUES(
          '.$this->getRebate()->getId().', 
          "'.mysql_real_escape_string(stripslashes($this->getCouponCode()), $conn_panier).'", 
          '.$this->getCodeUsage().', 
          "'.($this->getInvalidityDate() === NULL ? '0000-00-00 00:00:00' : date('Y-m-d G:i:s', strtotime($this->getInvalidityDate()))).'" 
         )', $conn_panier); 
     return (mysql_affected_rows($conn_panier) >= 1); 

    }else{ 

     //Update the existing rebate 
     mysql_query('UPDATE panier_rabais_codes 
         SET 
          `utilisation` = '.$this->getCodeUsage().', 
          `date_verrou` = "'.($this->getInvalidityDate() === NULL ? '0000-00-00 00:00:00' : date('Y-m-d G:i:s', strtotime($this->getInvalidityDate()))).'" 
         WHERE 
          no_rabais = '.$this->getRebate()->getId().' AND code_coupon = "'.mysql_real_escape_string($this->getCouponCode(), $conn_panier).'"', $conn_panier); 
     return (mysql_affected_rows($conn_panier) >= 0); 

    } 

} 

因此,您可以看到,代碼本身非常簡單且乾淨,如果插入成功則返回true,否則返回false。

while($codes_to_generate > 0){ 

    //Sleep to delay mysql choking on the input 
    usleep(100); 

    //Generate a random code 
    $code = strtoupper('RC'.$rebate->getId().rand(254852, 975124)); 
    $code .= strtoupper(substr(md5($code), 0, 1)); 
    $rebateCode = new Activis_Catalog_Models_RebateCode($rebate); 
    $rebateCode->setCouponCode($code); 
    $rebateCode->setCodeUsage($_REQUEST['utilisation_generer']); 
    try{ 
     if($rebateCode->saveChanges()){ 
      $codes_to_generate--; 
      $generated_codes[] = $code; 
     } 
    }catch(Exception $ex){ 
    } 

} 

正如你可以在這裏看到,有兩兩件事需要注意:

代碼的其他部分採用隨機算法,在是這樣產生的代碼。如果我從saveChanges返回true,那麼生成的代碼數和生成的代碼數組纔會被填充,所以mysql必須報告爲此部分發生的信息插入。

另一個珍聞是同時的第一行:

//Sleep to delay mysql choking on the input 
usleep(100); 

跆拳道?那麼這篇文章就是關於這個的。我的代碼完美地工作與少量的代碼生成。但是,如果我要求mysql一次保存超過幾個代碼,我必須使用usleep或mysql刪除這些行中的一部分。它會報告存在受影響的行但不保存它們。

在100行以下,我不需要調節,然後我需要根據要插入的行數量進行睡眠。它一定是簡單的東西,但我不知道是什麼。這裏是我試圖插入線和最小usleep油門的總和我不得不實現:

  • < 100行:無
  • < 300線:2毫秒
  • < 1000行:5毫秒
  • < 2000行:10毫秒
  • < 5000行:20毫秒
  • <萬線:100毫秒

謝謝您的時間

+0

您在查詢後沒有捕獲錯誤。這不是爲了弄清楚發生了什麼而採取的第一步嗎? –

+0

對不起,我已經這樣做了,沒有錯誤 –

+0

因此,您實際使用的代碼與您發佈的代碼有所不同嗎?真正的代碼在每次查詢後檢查錯誤?爲什麼不張貼代碼然後 –

回答

2

你確定你的代碼都插入並沒有更新,因爲更新不存在的線什麼都不做。

+0

你明白了,是「isNew()」檢查代碼是否已經存在,並且由於更新可能會導致在密鑰存在且沒有數據更改時更新0行,因此更新總是導致TRUE存儲代碼添加而不是更新。我強迫我的saveChanges(true)代替強制插入,現在它引發了一個異常,當代碼存在時強制正確地生成代碼。 –