我有一個基於SQLite數據庫的系統。每個客戶端都有一個本地數據庫,偶爾會有更新從主服務器到達,只是一個很小的delta .db文件。任務是使用增量文件合併到本地數據庫,模式在兩者中都是相同的。分離SQLite數據庫時出錯 - 數據庫被鎖定
對於我的數據庫管理,我使用可以找到here的fmdb包裝。在主線程中,我保持與本地數據庫的連接處於打開狀態。增量文件到達後臺,我想在後臺進行合併,以避免任何用戶界面凍結,這可能會導致。
至於合併本身,我發現的唯一選擇是將增量數據庫附加到本地數據庫,然後插入/更新行,最後分離增量。這並不像我預期的那樣順暢。
代碼描述:
- 的onDeltaGenerated方法在後臺線程中每當增量數據庫準備好被處理的(從服務器到達,並且被保存在可讀位置)調用。
- deltaDBPath是文件系統中增量數據庫的絕對位置。
- db變量引用打開FMDataBase連接。
代碼:
- (void)onDeltaGenerated:(NSNotification*)n {
NSString* deltaDBPath = [[n userInfo] objectForKey:@"deltaPath"];
@synchronized(db) {
[db executeUpdate:@"ATTACH DATABASE ? AS delta", deltaDBPath];
if ([db hadError]) {
NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]);
} else {
NSLog(@"Delta attached from %@", deltaDBPath);
}
[db beginTransaction];
BOOL update1 = NO;
BOOL update2 = NO;
BOOL transaction = NO;
update1 = [db executeUpdate:@"INSERT OR REPLACE INTO equipment SELECT * FROM delta.equipment"];
if (!update1) {
NSLog(@" *** ERROR *** update 1 failed!");
NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]);
}
update2 = [db executeUpdate:@"INSERT OR REPLACE INTO equipmentExt SELECT * FROM delta.equipmentExt"];
if (!update2) {
NSLog(@" *** ERROR *** update 2 failed!");
NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]);
}
transaction = [db commit];
if (!transaction) {
NSLog(@" *** ERROR *** transaction failed!");
NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]);
}
[db executeUpdate:@"DETACH DATABASE delta"];
if ([db hadError]) {
NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]);
} else {
NSLog(@"Delta detached");
}
}
}
後調用此方法的第一次,一切似乎是罰款,直到我試圖分離數據庫。當我嘗試這樣做,我得到以下錯誤:
2012-01-11 12:08:52.106 DBApp[1415:11507] Error calling sqlite3_step (1: SQL logic error or missing database) SQLITE_ERROR
2012-01-11 12:08:52.107 DBApp[1415:11507] DB Query: DETACH delta
2012-01-11 12:08:52.107 DBApp[1415:11507] ****ERROR*** 1: database delta is locked
我也試圖相同,但沒有把插入到交易,結果是相同的。另一件事是刪除@synchronized子句,但也沒有運氣。我的猜測是,如果嘗試從後臺線程訪問本地數據庫連接時失敗,但是如何管理附加和插入?任何幫助讚賞。
編輯
我感動的代碼到主線程,所以現在分貝,僅由主線程訪問。問題依然存在。
EDIT2
好了,所以亂投醫後,我放棄了這個一會兒再回來時,第一個答案出現在這裏。令人驚訝的是,現在一切都好了,所以我的代碼必須是正確的。我懷疑這是鎖定文件的不同線程的問題,因爲我使用XCode,SQLiteDatabaseBrowser和我的應用程序來打開數據庫。儘管lsof顯示該文件未被鎖定,但我認爲這是錯誤的,無論是XCode還是SQLiteDatabaseBrowser都在鎖定它。我認爲這個問題已經解決了,並且從中吸取的教訓並不是過分強調這一點,而是在下一次更好地規劃調試。
事務和executeUpdate方法都返回YES嗎? – Mark 2012-01-12 11:16:19
是的,他們這樣做。此外,我檢查了是否有其他進程正在鎖定數據庫(我使用fuser),但事實並非如此。到目前爲止,我一直在測試SIM卡,但是現在我發現它在iPod Touch上也無法運行,因爲出現同樣的錯誤。 – lawicko 2012-01-12 13:11:39
只需檢查:您的數據庫不存儲在NFS安裝的驅動器上,或者它是? – jogojapan 2012-03-02 04:54:47