Java Driver MongoDB GridFS Transaction

Java Driver 操作MongoDB GridFS 的資料正確性問題說明

葉文華 2016/07/22 17:45:32
1028







主題

Java Driver 操作MongoDB GridFS 的資料正確性問題說明

文章簡介

介紹Java Driver操作存取MongoDBGridFS時,將會碰到的資料正確性問題,即不符合資料庫Transaction的一致性(Consistency)問題說明

作者

葉文華

版本/產出日期

V1.0/2016.06.28




1. 前言

傳統資料庫如關聯式資料庫中,Transaction的ACID(Atomicity、Consistency、Isolation、Durability)是相當重要的特性,它保證了應用程式的錯誤恢復(rollback),得以信任資料的可靠性。

但是,MongoDB這類新興的資料庫中,可能不存在Transaction的概念或是只部分達到了ACID的特性,因此應用程式若需要確保資料符合該特性,只能以其特性相似的概念來實作達到。如MongoDB建議的Two-Phase Commit做法,提供了transaction-like的操作,仍可惜Java Driver層級提供的GridFS,由Driver底層實作了檔案拆分chunks寫入資料庫的機制,卻未支持Two-Phase Commit的實踐,相當容易造成資料一致性的錯誤。


ps. MongoDB保證了single-document atomic的操作結果。




2. 目的

初探Java Driver底層實作GridFS的機制,及可能發生資料一致性問題的情況說明,及提供應用程式面的最簡單解決方式




3. 開始前準備

Lib:mongo-java-driver-2.14.2.jar

Souce code:mongo-java-driver-r2.14.2.zip




4. 初探Java Driver實作GridFS機制

4.1、 GridFS建立出可寫入MongoDBGridFSInputFile(GridFSFile),以及透過GridFS移除


- GridFS建立GridFSInputFileGridFS的建構式中,將自動分成「.files」及「.chunks」兩個collections

com.mongodb.gridfs.GridFS

com.mongodb.gridfs.GridFSInputFile


- GridFSInputFile負責save迴圈切分檔案寫入chunks collecion,再寫入metadata資訊到files collection。由於過程中沒有實踐Two-Phase Commit,若寫入chunks collection圈遭到中斷,將造成寫入部分chunks或許仍不完整,且不存在files的問題,一致性問題即由此產生。

com.mongodb.gridfs.GridFSInputFile


com.mongodb.gridfs.GridFSInputFile

com.mongodb.gridfs.GridFSFile



4.2、 GridFS先查詢files中存在metadata資料,並轉由GridFSDBFile執行移除動作。若發生前述files未寫入問題,將不會自動刪除chunks中資料,並且GridFSDBFile中也是分別執行了remove filesremove chunks的動作,仍有可能造成移除不完整的一致性問題。


com.mongodb.gridfs.GridFS

com.mongodb.gridfs.GridFSDBFile


    


5. 驗證模擬資料一致性問題

5.1、 GridFS寫入過程中斷


經由迴圈寫入大檔案到MongoDB中,過程中直接停止程式的執行,模擬可能造成的process中斷或網路問題,並驗證資料確實出現chunks中已存在資料且不完整,但files中仍無metadata紀錄。



- 執行過程在第14cycle完成前中斷。


- 異常的資料,僅在chunks有檔案部分(4document)binary,已經成了垃圾資料。

        

- 底下正常的資料除了filesmetadata資訊外,chunks的完整數量是13document



5.2、 驗證移除操作


直接指定移除不完整的該筆GridFS資料,執行完成不會有任何訊息,但驗證資料的結果是沒有正確的刪除該筆資料,證實Java Driver在files中若沒有metadata紀錄的情況下,GridFS是沒有查詢結果,所以移除操作也將不會執行任何動作。



5.3、 再次寫入該筆資料


由於上述該筆資料,以正常GridFS進行查詢,將是沒有任何回傳結果。因此可能造成誤會該筆資料完全沒有寫入MongoDB中。以下驗證再次寫入時,將會發生DuplicateKey的問題。


- Java Driverchunks collection仍存在垃圾資料時,寫入將拋出以下錯誤




6. 處理GridFS寫入中斷發生的一致性錯誤問題

由於GridFS在這邊是由Java Driver底層實踐,正常的操作下指定該筆已異常的資料將無法查詢及移除。因此,可透過回歸傳統DBCollection的操作進行刪除在chunks collection的垃圾資料,便可以重新透過GridFS正常寫入該筆資料。





7. 參考來源

- 維基百科:資料庫-https://zh.wikipedia.org/wiki/ 資料庫

- Model Data for Atomic Operations-https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/

- Perform Two Phase Commits-https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits/



葉文華