Android事务 IMMEDIATE与EXCLUSIVE模式

事务是数据库保证数据唯一性和一致性的技术,对于数据库一个或一组写操作要保证是一个原子操作就需要使用事务,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。


本文出自 “ITLIFE” 博客,请务必保留此出处http://xwteacher.blog.51cto.com/9653444/1584555

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。