2013-01-08 65 views
9

我有一個mySQL更新查詢,有時會更新所有的字段,有時它會更新除一個之外的所有字段。更新查詢有時不會更新mySQL數據庫中的字段

約10%的通話失敗。

我的表是:

CREATE TABLE IF NOT EXISTS `grades` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`state` int(1) NOT NULL, 
`result` varchar(255) NOT NULL, 
`date_synced` datetime NOT NULL, 
`updated_at` datetime NOT NULL, 
PRIMARY KEY (`id`)) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4395 ; 

我的查詢是:

$sqlstr = "UPDATE grades SET result = '$result', state = 2, date_synced = '$date', updated_at = '$date' WHERE id = $id"; 

如果失敗的話,結果,date_synced和的updated_at被更新,但狀態保持不變。

還有一個查詢只更新狀態字段,而且一個查詢也間歇性地失敗。

我一直無法在我們的測試環境中重新創建問題。生產mySQL數據庫或某種鎖定衝突可能有問題嗎?


我有更多信息。我正在使用mysqli。另一個只更新狀態的查詢就是使用mysql。會導致問題嗎?

我以爲InnoDB是按行鎖定的。它不允許部分行更新,是嗎?


解決評論的另一個更新。

我的代碼流非常線性。

The row is created with state=0. 
<flash stuff here> and the row is updated with state=1 
A cron job pulls all state=1 and sends an api call 
if api call is successful, the row is updated with state=2, result, date_synced, and updated_at 
if api call is error, the row is updated with state=3, result, and updated_at 

狀態字段永遠不會設置爲0(在閃存之後)或1(在api調用之後)。由於日期_synced和結果正在設置,但(有時)狀態仍然爲1,這就像狀態字段的更新正在被丟棄。

我會添加更新觸發器,看看是否給了我更多的信息。

+3

您應該添加一個更新觸發器和一個記錄表,存儲舊值和新值以及id,會話ID和當前用戶以進行調試。也許這些變化已經通過,但被另一個聲明覆蓋 –

+1

我認爲Rufo先生的評論可能對你的情況有很大幫助,因爲它有助於確定事情發生的順序,以及是否是一個更復雜的情況,其中多個查詢結果在你看到的圖片中。 – DWright

+1

「[..]或某種鎖定衝突[..]」,因爲同一行內的其他字段已更新,因此您沒有鎖定問題。 innodb可以鎖定的最小的東西是一排。我無法鎖定單個字段。 – scones

回答

1

它是否表示「{n}行受到影響?」

另外,它是否可重複使用?你可以在完全相同的數據上運行相同的查詢,它會做不同的事情?

如果是這樣,您可能有損壞的安裝或損壞的數據庫。

您是否嘗試過修復&對錶格進行優化?這可能有幫助。

很抱歉的鉛彈答案:P

0

重新調整在MySQL的 「嚴」 傳統:

SET sql_mode = 'TRADITIONAL'; 

,並嘗試從控制檯插入,而不PHP。然後檢查可以解釋它的錯誤。

重置嚴格,以「寬容」的:

SET sql_mode = ''; 

或者,如果您使用PDO對象連接到數據庫,像這樣得到一個錯誤,回到通過PHP:

try { 
    $sqlstr = "UPDATE grades SET result = '$result', state = 2, date_synced = '$date',updated_at = '$date' WHERE id = $id"; 
$s = $pdo->exec($sqlstr); 
} 
catch (PDOException $e) { 
    $error = $e->getMessage(); 
    echo $error; 
} 

基本上,不管做什麼來獲取正在發生的錯誤信息。這很可能是SQL發送錯誤,但PHP未設置爲在腳本中顯示它。

+0

實際上,由於INT(1)已被截斷或很可能,MySQL很可能會生成警告。所以PHP可能會忽略警告並繼續。 –

+1

FWIW,INT(1)和INT(1000000)對於存儲和支持值的範圍完全相同。參數不是長度限制,而是顯示提示。 MySQL的INT始終是一個32位數據類型。 –

0

嘗試將字段的名稱從'state'更改爲其他內容,如'state_num'。雖然它沒有被列爲MySQL的保留字,但它的名字可能會導致問題。

0

您的查詢設置「狀態」和其他字段運行兩次,有時您的任務之一完成得比另一個更快。它更新所有字段,並且調用該任務的腳本也運行更新「狀態」字段的MySQL查詢。

例如,您有一個PHP腳本,它通過exec()在後臺運行shell命令「tar」,並在完成後在數據庫中設置「state」。下一串PHP代碼將更新數據庫中的「狀態」。但是有時你調用的bash命令比你的PHP腳本調用MySQL更新(如果這個bash命令在後臺模式下運行)運行得更快。

第一步:從PHP運行bash腳本,與完成日期,更新等領域後置「狀態」 = 3(等待進一步處理)等

下一步:在EXEC後,你的PHP()設置「狀態」= 2(進行中)。在這種情況下,如果後臺的bash腳本比PHP運行MySQL更新查詢更快地完成工作,那麼您將獲得更新的日期值以及「狀態」= 2(但它在一秒前具有值= 3)。

我有這個問題。