事务是数据库保证数据唯一性和一致性的技术,对于数据库一个或一组写操作要保证是一个原子操作就需要使用事务,android使用事务的常见形式如下:


SQLiteDatabasedb=null;...db.beginTransaction();try{db.setTransactionSuccessful();...}finally{db.endTransaction();}


那么db.beginTransaction是一个什么操作? 我们来看下SQLiteDatabase的源码:



/***BeginsatransactioninEXCLUSIVEmode.*<p>*Transactionscanbenested.*Whentheoutertransactionisendedallof*theworkdoneinthattransactionandallofthenestedtransactionswillbecommittedor*rolledback.Thechangeswillberolledbackifanytransactionisendedwithoutbeing*markedasclean(bycallingsetTransactionSuccessful).Otherwisetheywillbecommitted.*/publicvoidbeginTransaction(){beginTransaction(null/*transactionStatusCallback*/,true);}/***BeginsatransactioninIMMEDIATEmode.*Transactionscanbenested.When*theoutertransactionisendedalloftheworkdoneinthattransaction*andallofthenestedtransactionswillbecommittedorrolledback.The*changeswillberolledbackifanytransactionisendedwithoutbeing*markedasclean(bycallingsetTransactionSuccessful).Otherwisethey*willbecommitted.*/publicvoidbeginTransactionNonExclusive(){beginTransaction(null/*transactionStatusCallback*/,false);}

从注释中可以看到beginTransaction的调用使用EXCLUSIVE mode, beginTransactionNonExclusive使用IMMEDIATE mode,以上两个方法都是调用SQLiteDatabase的私有方法beginTransaction,两个方法不同之处在于第二个实参true|false, 这个私有方法源码:


privatevoidbeginTransaction(SQLiteTransactionListenertransactionListener,booleanexclusive){verifyDbIsOpen();lockForced(BEGIN_SQL);booleanok=false;try{...//Thisthreaddidn'talreadyhavethelock,sobeginadatabase//transactionnow.if(exclusive&&mConnectionPool==null){execSQL("BEGINEXCLUSIVE;");}else{execSQL("BEGINIMMEDIATE;");}...}finally{if(!ok){//beginTransactioniscalledbeforethetryblocksowemustreleasethelockin//thecaseoffailure.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。