2012-02-12 86 views

回答

2

Sqlite does not support nested transactions:使用BEGIN創建

交易...凱明不嵌套。對於嵌套的 事務,請使用SAVEPOINT和RELEASE命令。

我自己在SQLiteDatabase類中使用嵌套事務時遇到了死鎖問題,所以我強烈建議您遠離嵌套事務。使用自己的鎖來防止嵌套事務。

1

在兩個單獨的線程上創建兩個單獨的事務不被視爲「嵌套事務」。

每個線程都維護自己的數據庫會話,該數據庫會話映射到0或1個數據庫連接(如果會話不再需要連接,則可以從連接池中選擇數據庫連接並返回給它),因此在任何時間,會話是否有連接,取決於它是否需要)。

因此,每個線程維護其自己的交易狀態indepdnent其他線程。來源證實了這一點:

../Android/sdk/sources/android-23/android/database/sqlite/SQLiteDatabase.java:

// Thread-local for database sessions that belong to this database. 
// Each thread has its own database session. 
// INVARIANT: Immutable. 
private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() { 
    @Override 
    protected SQLiteSession initialValue() { 
     return createSession(); 
    } 
}; 

../Android/sdk/sources/android- 23 /安卓/數據庫/源碼/ SQLiteSession.java:

* <h2>About database sessions</h2> 
* <p> 
* Database access is always performed using a session. The session 
* manages the lifecycle of transactions and database connections. 
* </p><p> 

...

* Consequently, each thread 
* has its own session object and therefore its own transaction state independent 
* of other threads. 

所以,如果你有兩筆交易去在單獨的線程中,它們不是「嵌套」的,而是完全獨立的,並且將根據所涉及的交易的模式和類型(即,不管它們是否被推遲,立即,排他性以及它們是否被讀取或寫入)。

但是,必須正確使用Android SQLite庫來實現此目的。

我有2個線程訪問一個數據庫連接

如果這意味着兩個線程都使用相同的SQLiteSession,(雖然我不知道你怎麼能如果它甚至有可能做到這一點),那很可能導致僵局。

我的設置:

  1. 單個內容提供商
  2. 內容供應商初始化成員變量mDbHelper爲SQLiteOpenHelper在它的onCreate()
  3. 呼叫mHelper。getReadableDatabase/getWriteableDatabase根據需要在內容提供商的查詢/插入/ ...方法
  4. Android將處理確保使用內容提供商

如果長期運行的事務將是每個線程在不同的交易狀態在一個線程上執行(例如,從後臺線程同步數據導入),考慮使用db.yieldIfContended()db.yieldIfContendedSafely()來允許來自其他線程的事務(比如說或者記錄UI線程中的更新)擠入,以便它們不必等待長時間運行事務完成並阻止這些線程。

相關問題