2010-03-12 60 views
5

我正在開發一個使用SQLite3數據庫存儲數據的Visual C++應用程序。通常它大部分時間都在托盤中。SQLite文件鎖定和DropBox

我也想啓用將我的應用程序放入DropBox文件夾以在多臺PC上共享。 直到DropBox最近更新自己以前,它工作得非常好。 現在它說它「無法同步正在使用的文件」。 SQLite文件在我的應用程序中打開,但鎖是共享的。有一些準備好的陳述,但是在使用step後立即重置。

有什麼辦法可以同步打開的SQLite數據庫文件嗎?謝謝!

下面是簡單的包裝,我使用只是爲了測試(沒有錯誤處理)的情況下,這有助於:

class Statement 
{ 
private: 
    Statement(sqlite3* db, const std::wstring& sql) : db(db) 
    { 
    sqlite3_prepare16_v2(db, sql.c_str(), sql.length() * sizeof(wchar_t), &stmt, NULL); 
    } 

public: 
    ~Statement() { sqlite3_finalize(stmt); } 

public: 
    void reset() { sqlite3_reset(stmt); } 
    int step() { return sqlite3_step(stmt); } 
    int getInt(int i) const { return sqlite3_column_int(stmt, i); } 

    std::wstring getText(int i) const 
    { 
    const wchar_t* v = (const wchar_t*)sqlite3_column_text16(stmt, i); 
    int sz = sqlite3_column_bytes16(stmt, i)/sizeof(wchar_t); 
    return std::wstring(v, v + sz); 
    } 

private: 
    friend class Database; 

    sqlite3* db; 
    sqlite3_stmt* stmt; 
}; 


class Database 
{ 
public: 
    Database(const std::wstring& filename = L"")) : db(NULL) 
    { 
    sqlite3_open16(filename.c_str(), &db); 
    } 

    ~Database() { sqlite3_close(db); } 

    void exec(const std::wstring& sql) 
    { 
    auto_ptr<Statement> st(prepare(sql)); 
    st->step(); 
    } 

    auto_ptr<Statement> prepare(const std::wstring& sql) const 
    { 
    return auto_ptr<Statement>(new Statement(db, sql)); 
    } 

private: 
    sqlite3* db; 
}; 

UPD:試了註釋掉sqlite3.c到與LockFile和LockFileEx所有呼叫 - 相同的結果。

UPD2:試圖在閒置時調用sqlite3_close(就像概念驗證一樣) - 仍然是相同的結果! Filemon告訴該文件仍然沒有關閉,只能解鎖。

UPD3:自動提交模式開啓。 BEGIN和COMMIT的數量相符(類交易和RAII負責)。 SQliteManager能夠在我的應用程序運行時連接到數據庫並對其進行修改。

+1

您是否檢查sqlite3_close()的結果?也許這不起作用,因爲你還沒有完成所有你準備好的陳述。 – 2010-03-15 12:57:32

+0

就是這樣!由於正在運行的後臺備份,它無法工作。愚蠢的錯誤..謝謝!把它作爲答案,我會接受它。 – 2010-03-16 08:45:16

回答

4

檢查sqlite3_close()的結果。也許這不起作用,因爲你還沒有完成所有你準備好的陳述。

2

你在使用什麼文件系統?

您確定autocommit已開啓和/或您是否提交了您的陳述嗎?我記得有一個沒有提交的問題,鎖會保持不變。

+0

NTFS。關於提交的好主意,謝謝,我會檢查這是否可能。 – 2010-03-14 08:47:06

+0

自動提交模式開啓。 BEGIN和COMMIT的數量相符(類交易和RAII負責)。似乎這不是原因。 SQliteManager能夠在我的應用程序運行時連接到數據庫並對其進行修改。 – 2010-03-14 09:14:17

2

Alex Pechnikov有一個多主SQLite數據庫複製程序sqlite3-rdiff。對於你正在努力完成的任務來說,這可能是矯枉過正的,但它可能比文件複製更容易。

SQLite也有Online Backup API;該頁面上有一個示例:示例2:正在運行的數據庫的聯機備份。

+0

我想不出如何自動使用它。 sqlite3-rdiff需要Tcl,並且使用備份API意味着在每次更改後複製整個數據庫。 – 2010-03-15 08:11:01

+0

DropBox是否在每次更改後都製作數據庫的副本(或rdiff)?如果是這樣,本地副本沒有太多的開銷。如果不是,那麼只需在DropBox需要的地方拷貝本地拷貝。 – 2010-03-15 19:25:34