2017-10-14 99 views
0

...我已經尋找很多類似的問題,但我無法找到任何間歇返回0SELECT LAST_INSERT_ID()返回間歇0

****編輯*****

,因爲我有嘗試用只有兩列的新表進行測試,將問題減少到50次左右,返回0。

我也剛剛現在已經能夠測試支付託管服務器上,我不能複製我的問題

我想這個問題我是特定於虛擬主機。

問題:

當試圖檢索在每個連接的基礎上最後插入的ID,大約400十次中有我得到一個0退還給我。

Localhost,一切工作正常,沒有問題。只有當我的網站託管在服務器上時纔會出現此問題。

SELECT LAST_INSERT_ID() intermittently returns 0 

$PDOconnection->lastInsertId(); Always returns correct ID 

我需要得到可靠的最後插入的ID在每個連接的基礎,因爲它在數據庫中創建採購訂單時對我的網站的結賬過程是必不可少的。

注:

  • 的ID是自動遞增
  • SQL插入一直工作正常,數據庫顯示了一個新的條目。
  • 切換PHP版本不能解決
  • 我使用
  • 虛擬主機是我使用現場 測試目的
  • 頁面加載時間免費託管服務的問題總是相似(500 - 750毫秒的代碼下面)

我剝去了整個​​代碼(如下)以簡單測試。問題仍然存在

我似乎無法鍛鍊我的問題在哪裏。

include_once "php/config.php"; 

$cookie_id = 0; 

// Time of checkout 
$time = gmdate("d/m/Y h:i:s"); 

// Create new purchase order 
$sql_insert = "INSERT INTO user_purchases (cart_id, timestamp) VALUES (:cookie_id, :time)"; 

$stmt_insert = $PDOconnection->prepare($sql_insert); 
$stmt_insert->bindParam(':cookie_id', $cookie_id, PDO::PARAM_STR); 
$stmt_insert->bindParam(':time', $time, PDO::PARAM_STR); 
$stmt_insert->execute(); 

$checkout_id_0 = $PDOconnection->lastInsertId(); 

// Get the primary key id of the last inserted item on per-connection basis 
$sql_last_id = "SELECT LAST_INSERT_ID()"; 
$stmt_last_id = $PDOconnection->prepare($sql_last_id); 
$stmt_last_id->execute(); 
$r_last_id = $stmt_last_id->fetch(PDO::FETCH_ASSOC); 

$checkout_id_1 = $r_last_id['LAST_INSERT_ID()']; 

echo $checkout_id_0 . " " . $checkout_id_1; // I echoed out to observe results 

連續10次查詢結果的真實例子(只需刷新頁面即可)。我並排地迴應了結果。

checkout_id_0  $checkout_id_1 <---SELECT LAST_INSERT_ID() 

     16    16 
     17    17 
     18    0  // Returned 0 
     19    19 
     20    0  // Returned 0 
     21    0  // Returned 0 
     22    22 
     23    23 
     24    23  // Returned previous ID (happens 1/30 tries) 
     25    25 

連接配置:

$PDOconnection = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $sql_username, $sql_password); 

// Set PDO error mode to exception 
$PDOconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

// Set PDO Attribute to force native prepared statements 
$PDOconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
+3

任何理由,爲什麼你不能使用值從'lastInsertId'回來了?你在用'mysqlnd'嗎? (..哪些[支持連接池,其中一個新的,不同的連接可能用於每個查詢](http://php.net/manual/en/mysqlnd-ms.pooling.php))。 – MatsLindh

+0

使用mysqlnd。在印象中,我認爲SELECT LAST_INSERT_ID()在電子通信結賬方案中更可靠,因爲您只能獲得爲特定客戶端返回的ID。 – user3796133

+0

@MatsLindh自從我嘗試過使用僅有兩列的新表格進行測試以來,它已將問題減少到50次左右,返回0。我現在也剛剛能夠在付費託管服務器上進行測試,並且我無法複製我的問題,我認爲該問題特定於該Web主機。 – user3796133

回答

0

您是否嘗試激活持久連接?請參閱Connections and Connection managementPersistent Database Connections。也許這個遠程服務器的MySQL設置太短了 - wait_timeoutinteractive_timeout ...

持久連接未封閉在腳本的結束,但 被緩存,並且當另一個腳本請求使用 相同憑證的連接重新使用。持久連接緩存允許您在每次 腳本需要與數據庫交談時避免建立新連接的開銷,從而產生更快的Web應用程序。

還要注意:

如果你想使用持久連接,就必須傳遞給PDO 構造驅動選項數組中設置 PDO :: ATTR_PERSISTENT。如果在 對象的實例化後使用PDO :: setAttribute()設置此屬性,驅動程序將不會使用持久性 連接。

所以:

$PDOconnection = new PDO(
    "mysql:host=$servername;dbname=$dbname;charset=utf8" 
    , $sql_username 
    , $sql_password 
    , array(
     PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 
     PDO::ATTR_EMULATE_PREPARES => false, 
     PDO::ATTR_PERSISTENT => true, 
    ) 
);