2010-05-16 99 views
2

我有一個長時間運行的應用程序,用C和C++的混合編寫,它在sqlite中存儲數據。雖然我確信承諾的數據將保持可用(禁止機械故障)並且未提交的數據將不會被使用,但我不清楚在這種中間狀態下我能做些什麼。我應該如何處理sqlite錯誤?

我在事務中做了大量的插入操作,然後提交它。當給定語句發生錯誤時,我可以安排它在將來的某個時間點嘗試。這聽起來像一些錯誤可能會隱式回滾我的交易(如果屬實,這將是不受歡迎的)。

更大的問題是當我的提交失敗時會發生什麼。目前,我只是繼續重試它,直到它工作。我希望無論什麼會導致我的提交失敗也可能導致回滾失敗。

在這種情況下,錯誤處理的推薦機制是什麼?

回答

1

在COMMIT上,如果看到SQLITE_BUSY錯誤,則應該重新嘗試 COMMIT。它可能工作。更好的是,安裝一個忙處理器回調函數 來處理SQLITE_BUSY。

COMMIT可能失敗的另一個原因是延期的外鍵 違規。如果發生這種情況,您可以修復FK違規,然後修改COMMIT。很難看到這樣做的無人應用程序。

其他錯誤你應該放棄和ROLLBACK 交易。

如果發生IO或OOM錯誤,當前事務可能會回滾到 。這是因爲某些IO或OOM錯誤使SQLite 不確定其內部數據結構是否匹配 磁盤上的實際內容。如果我們在這一點上繼續進行 數據庫可能會損壞。您可以使用sqlite3_get_autocommit()API測試SQLite是否已回滾事務 。

如果在COMMIT過程中發生IO或OOM錯誤,則事務可能仍會提交 。例如,如果 用戶碰巧從存儲卡中取出存儲卡,就會發生這種情況,就像提交了事務 一樣。如果數據在不讀取 數據庫並在應用程序級別進行檢查的情況下將數據寫入持久性介質,通常無法知道 。

+1

這聽起來非常接近我在找的東西。如果回滾本身失敗,我該怎麼辦? – Dustin 2010-05-17 06:27:46

0

無論您嘗試多少次,在不可空列中插入空值都不太可能成功。

沒有單一的解決方案,您的問題。例如,如果您違反了數據庫約束條件,則應該在再次嘗試之前更改您的數據。如果你沒有剩餘內存/磁盤空間 - 釋放一些並重試。

我想你需要了解更多關於交易和ACID屬性。

0

數據庫是明確設計的,因此數據總是提交或未提交。當提交數據時,它不會隨意丟失,因爲它是永久存儲的(當然,在磁盤文件中,這是一個很好的近似值)。如果您正在進行手動事務管理(聽起來像是這樣),那麼數據庫不會 COMMIT或ROLLBACK,直到詢問爲止。語句中的錯誤可以處理,而不會丟失任何已經完成的事情。

如果您處於無法執行COMMIT或ROLLBACK的狀態,那麼您遇到了麻煩。如果這是因爲內存不足或磁盤空間不足(或配額),那麼您已將應用程序配置爲錯誤,並且應該先解決該問題。

您也可能想要限制事務的長度,以便在出現故障時不會造成災難性的後果(在恢復工作方面)。

+0

調整事務處理的大小非常簡單 - 我只是將它們分配給性能。在某些情況下,我有可能進入我發送了一堆成功的語句的狀態,但最終的提交可能會出錯。這個問題主要是sqlite特定的。從文檔中不清楚何時重複提交是否正確。 – Dustin 2010-05-16 06:46:32

+0

好吧,由於事情可以在自動提交模式下運行,並且由於某些錯誤是災難性的事實,因此文檔變得更加複雜。 (磁盤用完就是一個例子!) – 2010-05-16 07:04:14

+0

我實際上已經測試過磁盤空間不多了 - 至少對於事務中的插入。我得到的是更多的零星磁盤故障。 EC2是一個惡劣的環境。我相信sqlite的健壯性可以幫助我安全地遍歷它。 – Dustin 2010-05-16 07:12:03

0

雖然我不同意以前的答案,SQLite絕對可以遇到暫時的錯誤,這將允許您只需重試幾次就可以成功執行COMMIT,但他們確實有一個關於這不適用於所有錯誤的好處。不要忘記實施重試限制,也許還要檢查失敗的原因,而不是盲目地重試。

+0

在我的申請中放棄沒有合乎邏輯的觀點。測試人員使用人工IO子系統錯誤生成器來驗證我是否重試了錯誤。操作必須嘗試修復IO,或者接受它不會發生並取下整個服務器。 – Dustin 2010-05-16 18:41:26

相關問題