2014-02-25 79 views
0

由於地理或Internet提供商問題,某些用戶在使用我們的系統時無法連接WiFi。當某些用戶保存一些產品信息時,我發現一些數據(字段)不是100%保存到數據庫中。這對我來說很難再現問題,因爲我的聯繫很好。防止由於WiFi連接不良而導致數據庫損壞

所以我的問題是如何讓服務器知道我已經發送所有字段進行處理之前保存/更新查詢執行?

case "save": 

for ($i=0, $n=sizeof($languages); $i<$n; $i++) 
{ 
    $language_id = $languages[$i]['id']; 
    $name = preg_replace('/\s+/', ' ', tep_db_prepare_input($_POST["products_name"][$language_id])); 
    $description = tep_db_prepare_input(str_replace("&nbsp;", " ", $_POST["products_description"][$language_id])); 
    $extra_info = tep_db_prepare_input(str_replace("&nbsp;", " ", $_POST["products_extra_info"][$language_id])); 

    tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', 'products_id = "' . $pID . '" AND language_id="'.$language_id.'"'); 

    // update other language that empty 
    $sql_data_array = array('products_name' => $name); 
    tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', 'products_id = "'.$pID.'" and products_name = ""'); 

    $sql_data_array = array('products_description' => $description); 
    tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', 'products_id = "'.$pID.'" and products_description = ""'); 

    $sql_data_array = array('products_extra_info' => $extra_info); 
    tep_db_perform(TABLE_PRODUCTS_DESCRIPTION, $sql_data_array, 'update', 'products_id = "'.$pID.'" and products_extra_info = ""'); 
} 

... etc 
+5

使用數據庫__transactions__ –

回答

2

使用數據庫事務可以防止這些錯誤。 如果出現問題,則不會對數據庫執行更新。 請注意,您不能在MyISAM表使用事務,你需要使用InnoDB的發動機

+0

爲我檢查我們的數據庫使用的MyISAM,這種情況的選項? – rusly

+0

MyISAM比InnoDB更快,但不保證對錯誤的高級數據保護。如果您不需要高性能,請嘗試將錶轉換爲InnoDB引擎: http://dev.mysql.com/doc/refman/5.6/en/converting-tables-to-innodb.html –

1

您需要使用transaction來執行多個數據庫查詢。其優點是,如果其中一個查詢在執行中失敗,則所有先前執行的所有操作都會在數據庫中取消。這樣你的數據庫中就沒有任何損壞或不完整的數據。

-1

除了@Mark Ba​​ker所陳述的顯而易見外,您可以使用PHP的connection_aborted()函數來檢測用戶何時斷開連接。下面是從評論部分摘錄:

-

了一個小竅門,如果一個連接,而無需發送,將數據以其他方式破壞流(如二進制文件),你可以使用數據封閉檢測在HTTP/1.1上通過發送「0」(「零」)作爲前導塊大小而不用其他任何東西來分塊數據。

注意重要的是要注意,每隔幾秒檢查一次流並不是一個好主意。通過這樣做,您可能會增加發送給用戶的數據,而不會爲用戶帶來收益。

這樣做的一個很好的理由是,如果您生成報告需要很長時間才能運行並佔用大量服務器資源。這將允許服務器檢測用戶是否取消下載並進行任何清理而不會破壞正在下載的文件文件。

下面是一個例子:

<?php 
ignore_user_abort(true); 
header('Transfer-Encoding:chunked'); 
ob_flush(); 
flush(); 
$start = microtime(true); 
$i = 0; 
// Use this function to echo anything to the browser. 
function vPrint($data){ 
    if(strlen($data)) 
     echo dechex(strlen($data)), "\r\n", $data, "\r\n"; 
    ob_flush(); 
    flush(); 
} 
// You MUST execute this function after you are done streaming information to the browser. 
function endPacket(){ 
    echo "0\r\n\r\n"; 
    ob_flush(); 
    flush(); 
} 
do{ 
    echo "0"; 
    ob_flush(); 
    flush(); 
    if(connection_aborted()){ 
     // This happens when connection is closed 
     file_put_contents('/tmp/test.tmp', sprintf("Conn Closed\nTime spent with connection open: %01.5f sec\nLoop itterations: %s\n\n", microtime(true) - $start, $i), FILE_APPEND); 
     endPacket(); 
     exit; 
    } 
    usleep(50000); 
    vPrint("I get echo'ed every itteration (every .5 second)<br />\n"); 
}while($i++ < 200); 
endPacket(); 
? 

注:此行ignore_user_abort(true);允許腳本繼續在用戶斷開連接後在後臺運行,沒有它(即默認情況下)PHP的過程中當場死亡。這就是爲什麼使用交易將解決您的問題作爲開始的交易,從未完成。