您好,登錄后才能下訂單哦!
事務是數據庫保證數據唯一性和一致性的技術,對于數據庫一個或一組寫操作要保證是一個原子操作就需要使用事務,android使用事務的常見形式如下:
SQLiteDatabase db = null; ... db.beginTransaction(); try { db.setTransactionSuccessful(); ... } finally { db.endTransaction(); }
那么db.beginTransaction是一個什么操作? 我們來看下SQLiteDatabase的源碼:
/** * Begins a transaction in EXCLUSIVE mode. * <p> * Transactions can be nested. * When the outer transaction is ended all of * the work done in that transaction and all of the nested transactions will be committed or * rolled back. The changes will be rolled back if any transaction is ended without being * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. */ public void beginTransaction() { beginTransaction(null /* transactionStatusCallback */, true); } /** * Begins a transaction in IMMEDIATE mode. *Transactions can be nested. When * the outer transaction is ended all of the work done in that transaction * and all of the nested transactions will be committed or rolled back. The * changes will be rolled back if any transaction is ended without being * marked as clean (by calling setTransactionSuccessful). Otherwise they * will be committed. */ public void beginTransactionNonExclusive() { beginTransaction(null /* transactionStatusCallback */, false); }
從注釋中可以看到beginTransaction的調用使用EXCLUSIVE mode, beginTransactionNonExclusive使用IMMEDIATE mode,以上兩個方法都是調用SQLiteDatabase的私有方法beginTransaction,兩個方法不同之處在于第二個實參true|false, 這個私有方法源碼:
private void beginTransaction(SQLiteTransactionListener transactionListener, boolean exclusive) { verifyDbIsOpen(); lockForced(BEGIN_SQL); boolean ok = false; try { ... // This thread didn't already have the lock, so begin a database // transaction now. if (exclusive && mConnectionPool == null) { execSQL("BEGIN EXCLUSIVE;"); } else { execSQL("BEGIN IMMEDIATE;"); } ... } finally { if (!ok) { // beginTransaction is called before the try block so we must release the lock in // the case of failure. unlockForced(); } } }
當形參exclusive為true并且mConnectionPool==null是執行:execSQL("BEGIN EXCLUSIVE;"); false執行execSQL("BEGIN IMMEDIATE;");
BEGIN EXCLUSIVE:當前事務在沒有結束之前任何android中的其他線程或進程都無法對數據庫進行讀寫操作。
BEGIN IMMEDIATE:確保android中其他線程或者進程之間讀取數據不能修改數據庫。
為什么需要判斷mConnectionPool==null這個條件,如果當mConnectionPool!=null 表示調用了enableWriteAheadLogging,也就是使用了WAL MODE。 使用WAL模式是能夠提高并發性,讀與寫互不阻塞,而執行BEGIN EXCLUSIVE卻降低了并發,互相矛盾,所以當以上兩個條件都成立的情況下執行BEGIN EXCLUSIVE。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。