-- Leo's gemini proxy

-- Connecting to ramax.flounder.online:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; charset=utf-8

SQLite3 的強健性考量


SQLite3[1] 由於體積小、速度快,支援 SQL 語法,相信是眾多系統開發者心目中嵌入式小型資料庫的首選,敝公司當然也不例外。不過最近有時會發現有幾台安裝在客戶那的機器出現資料庫檔案寫壞的情況。雖然照著這裡[2]所寫的步驟可以把一些記錄救回來,然而該資料庫儲存著錄影檔回放時所需要的時間區段記錄,按目前的程式邏輯,如果發現某個錄影檔在資料庫內沒有對應的記錄,那麼就會把該檔給刪除,以免佔用空間。


1: https://sqlite.org/index.html

2: https://techblog.dorogin.com/sqliteexception-database-disk-image-is-malformed-77e59d547c50


問題就出在這裡。從寫壞的資料庫所救回來的資料並不是完整的,勢必會缺少一些記錄,因此程式就會把不存在記錄的錄影檔給刪掉。有時所缺少的記錄橫跨了一個禮拜,那就表示會有一整個禮拜的歷史影像就只因為資料庫寫爛了,就被砍掉了。萬一有重要事件在這一段時間發生,客戶就再也無法調出來看了。這真的是很令人困擾的事。


我花了很多時間在研究為何資料庫檔案會被寫爛這件事。SQLite3 不同於一般的資料庫,它從一開始就是特別為了嵌入式的應用而設計,因此針對嵌入式系統中常見的插拔電情況設計了一套復原機制[3]。從文件的解說中看來也確實是無懈可擊,不過這裡[4]也提到了以下幾種可能會讓復原機制失效的情況:


3: https://sqlite.org/atomiccommit.html#_rollback

4: https://sqlite.org/atomiccommit.html#_things_that_can_go_wrong


不良的檔案系統鎖定實作

不完整的磁碟寫入 (`fsync()`)

不完整的檔案刪除

其他存取資料庫的行程意外寫入了垃圾資料

Hot journal 被刪除或被改名


另外由於資料庫檔案是寫在 SD 卡中,還需要考慮 SD 卡寫壞的情況。


我想了很久,後來發現就算找出了原因,很有可能我也沒有時間與能力去修正 (不論是 SD 卡的問題或是檔案系統的問題)。那麼為何不乾脆使出強健系統的終極奧義呢?


何謂強健系統的終極奧義?概念超級簡單,就是多存幾份備份。君不見 RAID 不也是基於相同的概念嗎?只要想辦法將這些記錄在儲存於資料庫的同時,也將其備份分散存放在其他地方,那麼當資料庫壞掉時,系統就能夠再從這些地方取回紀錄以重建資料庫了。


似乎是個值得思考的方向。

-- Response ended

-- Page fetched on Sat May 18 04:58:52 2024