簡體   English   中英

Android:如何鎖定可通過ContentProvider訪問的SQLite數據庫(或執行原子條件操作的其他方式)

[英]Android: how can I lock SQLite database accessible with ContentProvider (or other way of executing atomic conditional operations)

我在SQLite DB中得到了兩個表: entitiesuser_actions 他們的近似方案:

在此處輸入圖片說明

程序的流程是這樣的(ContentProvider處理的所有數據庫訪問):

  1. 用戶執行一些修改實體之一的動作
  2. 相應實體立即在entities更新。 此實體的locally_modified值設置為1
  3. 有關用戶操作的信息存儲在user_actions
  4. 將來的某個時候,將啟動與服務器的同步會話(我使用SyncAdapter框架)
  5. user_actions中的用戶操作被user_actions上傳到服務器,並在后台線程中從數據庫中刪除
  6. 上傳完成后,我需要清除entities locally_modified標志

在這一點上,我遇到了我的原子性問題:與服務器的同步發生在后台線程中,因此用戶可以使用該應用程序並執行其他操作。 因此,在清除實體的locally_modified標志之前,必須檢查user_actions是否沒有與此實體對應的記錄。 對於locally_modified設置為1每個實體,必須自動執行這三個步驟:

  1. 查詢user_actions以獲取與實體的_id對應的條目
  2. 測試來自#1的查詢是否返回空集
  3. 將該實體的locally_modified清除為0

在上述情況下,我有三個問題:

問題1:有沒有一種方法可以鎖定通過Android中的ContentProvider訪問的SQLite DB,使其只能由鎖定線程訪問?

Q2:如果對Q1的回答是肯定的,那么如果其他某個線程試圖訪問鎖定的DB,會發生什么? 我應采取哪些預防措施以確保可靠運行?

問題3:可以使用ContentProviderOperation使用條件邏輯執行原子事務嗎? 您可以使用此答案此博客文章中所述的“反向引用”來引用先前操作的結果,但是是否可以在某種if-else語句中使用該結果?

謝謝

有沒有一種方法可以鎖定Android中的SQLite DB,使其只能由鎖定線程訪問?

是的,看看SQLiteDatabase.beginTransaction() )。 我相信您需要SQLite的專有事務 ,但是您需要對它的確切用途進行更多研究。

如果對Q1的回答是肯定的,那么如果其他線程嘗試訪問鎖定的DB會發生什么? 我應采取哪些預防措施以確保可靠運行?

您可以檢查一個SQLite.amIInTransaction()方法,或者僅捕獲一個SQLiteDatabaseLockedException您應該查詢更多的SQLite異常

是否可以使用ContentProviderOperation使用條件邏輯執行原子事務? 您可以使用此答案和此博客文章中所述的“反向引用”來引用先前操作的結果,但是是否可以在某種if-else語句中使用該結果?

從來沒有做過,但是似乎重寫ContentProvider的applyBatch並將其包裝在事務中應該可以工作:

Android:使用ContentResolver時的SQLite事務

答案很簡單,但這是一種“ hack”-只需向ContentProvider添加其他Uri

例如:最初,我的ContentProvider支持以下URI:

  • Uri.withAppendedPath(MyContract.CONTENT_URI, "entities")
  • Uri.withAppendedPath(MyContract.CONTENT_URI, "user_actions")

為了支持問題中描述的原子操作,我添加了一個額外的Uri

  • Uri.withAppendedPath(MyContract.CONTENT_URI, "clear_modified_flag")

通過以下方式更新此Uri

getContentResolver().update(
    MyContract.ClearModifiedFlag.CONTENT_URI,
    new ContentValues(),
    null,
    null);

我的ContentProvider執行一個SQLite transaction ,該transaction將在操作期間鎖定數據庫,並在發生任何錯誤的情況下回滾該數據庫(如本答案所述 )。

而已。

PS我的ContentProvider未導出(即其他應用程序無法訪問和使用它),因此可以安全地添加此新Uri 但是請記住,如果您確實導出了ContentProvider ,則暴露這樣的功能可能會出現問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM