2015-08-26 15 views
1

當使用C++的sqlite庫時,在sqlite3_stmt上調用sqlite3_step可能會以幾種不同的方式失敗。就我的理解而言,除了一個之外,他們都應該導致例外或者由編程錯誤引起。塊sqlite步驟,直到數據庫不再繁忙

然而,其中一個令我感到困惑:SQLITE_BUSY。我的意思是:SQLITE_BUSY只是意味着數據庫被鎖定,因爲一些事務已經在它上面發生了,對吧?假設某個不同的流程已經開始交易並且尚未提交或發佈,則任何試圖編輯數據庫或開始新交易的sqlite3_step調用都將失敗,並且SQLITE_BUSY將失敗。

但是,這對我來說不是一個錯誤:當一個資源被使用時,我可以......等等!與互斥體不同(可能更復雜),我想應該可以阻止當前線程/進程的執行,直到再次訪問共享資源爲止。

有沒有辦法做這樣的事情?我想要的是以下形式:

sqlite3_step_or_block_until_available_then_step(my_stmt); 

因此,執行被阻止,直到數據庫不再忙,我可以使用它。有沒有由sqlite庫本身提供的解決方案?如果不是,我該怎麼辦?我的意思是,我顯然可以忙着等到SQLITE_BUSY錯誤不再返回,但它並沒有什麼意義,因爲它消耗了大量資源。是否有更多的表現方式來實現這一目標?

如果可能,請提供一些簡短的示例,以便我能夠理解如何使其發揮作用!

+0

你周圍應提供自己的鎖定機制訪問數據庫。 –

回答

0

你可以鎖定數據庫自己與使用互斥的,但sqlite3的確實provide a mechanism that might help(重點煤礦):

SQLITE_BUSY
的SQLITE_BUSY結果代碼表示數據庫文件無法寫入(或某些情況下讀取),因爲某些其他數據庫連接的併發活動,通常是單獨進程中的數據庫連接。
例如,如果進程A處於大型寫入事務的中間,並且同時進程B嘗試啓動新的寫入事務,則進程B將取回SQLITE_BUSY結果,因爲SQLite一次只支持一個寫入器。進程B需要等待進程A在開始新的事務之前完成其事務。 sqlite3_busy_timeout()sqlite3_busy_handler()接口和busy_timeout pragma可用於處理B以幫助它處理SQLITE_BUSY錯誤。

可以register a callback to handle SQLITE_BUSY所以不是數據庫返回SQLITE_BUSY它會調用您的處理程序。有關這方面的限制,您可以在鏈接中閱讀。

我不會爲此提供示例,因爲我覺得解決您的having multiple threads access a database問題的可能性較小,因爲每個數據庫連接只能有一個繁忙處理程序。

如果像我從your previous question懷疑,你必須對所有的代碼訪問數據庫的控制,那麼它可能只是被證明更容易使用std::mutexstd::conditional_variable

{ 
    std::lock_guard<std::mutex> lock(dbMutex); 
    sqlite3_stmt(...); 
} 
+0

只有當您是阻止數據庫的人員(即相同的進程或您控制的所有進程)時纔有效,但情況可能並非如此。 – Blindy

+0

@ Blindy如果多個進程可以訪問數據庫,但沒有控制權,那麼可以使用sqlite提供的機制(我在答案中提到) – Tas