Android & SQLite3 LockとTransaction Immediate/Exclusive

Intro
------------------------------------------------------

AndroidのSQLite3のLockとTransaction Immediate/Exclusiveについてまとめた. 
基礎となる知識としては 下記 を参照. 

 - [Yukiの枝折 - Android: SQLite3 LockとTransaction Immediate/Exclusive](http://yuki312.blogspot.jp/2014/10/android-sqlite3.html)
 - [Qiita - 同時実行制御とSQLite3](http://qiita.com/Yuki_312/items/7a7dff204e67af0c613a)

Locking And Concurrency In SQLite3
------------------------------------------------------

Oracle等のDBMSでは"行ロック"など細かくロック粒度を制御できるが, SQLiteではこれができない. 
SQLiteのロック粒度は"データベース単位"のみである. このためRead/Writeロック取得～解放までの間, 他のトランザクションはデータベースにアクセスできない. (このことは"データベースを分割する/しない"の判断基準の１つにはなりそう)

AndroidではSQLiteのトランザクションモードとしてImmediateとExclusiveをAPIで指定できる. 特に指定しない場合はExclusiveモードとなる. 

### Transaction Immediate

ロック取得中は他トランザクションの書き込みを制限し, 読み込みを許可するmode. 
Exclusive modeより緩い分離レベルであるためトランザクションの並列化を促進でき, パフォーマンス面で期待できる. ただし, Phantom Readが発生する可能性を考慮する必要がある. 

> IMMEDIATE. 
> トランザクション開始時にRESERVEDロックを取得する. BEGIN IMMEDIATEによりRESERVEDロックが取得されると, 他のデータベースコネクションはデータベースに書き込んだり, BEGIN IMMEDIATE or BEGIN EXCLUSIVEを実行することができなくなるが, データベースからの読み込みを継続することはできる. 
ANSI/ISO SQL標準では `REPEATABLE_READ` に相当する. 

アプリケーションがデータベースへアクセスするのに書き込み専用トランザクション と 読み込み専用トランザクションのようにRead/Writeを分離できるのであればImmediate modeは有効に作用する. 

Immediate modeではPhantom Readが発生するため, 次のようなシーケンスでは一貫性が損なわれる. 

![Phantom Read](https://qiita-image-store.s3.amazonaws.com/0/3888/0eaaf435-40b6-0d60-f618-9e62b1aa2f15.png)


### Transaction Exclusive

ロック取得中は他トランザクションの読み込み/書き込みを制限するmode.
Immediateより厳しい分離レベルであるためトランザクションの直列化が促進され, データの一貫性が向上する. ただしパフォーマンスはImmediateに劣る可能性が高い. 

> EXCLUSIVE
> トランザクション開始時にEXCLUSIVEロックを取得する. BEGIN EXCLUSIVEによりEXCLUSIVEロックが取得されると, READ_UNCOMMITTEDの接続を除いた全てのデータベースコネクションからデータを読み込むことができなくなる. データベースへの書き込みについては例外なくトランザクションの完了まで許可されない. 
ANSI/ISO SQL標準では `SERIALIZABLE` に相当する. 

データベースに対して完全なデータの一貫性が求められる場合はExclusive modeを指定する. 



Implements
------------------------------------------------------

クライアントからTransaction modeを指定するには`SQLiteDataBase`クラスを使用する. 

 - `SQLiteDataBase.beginTransaction()`
 - `SQLiteDataBase.beginTransactionWithListener(SQLiteTransactionListener)`
 - `SQLiteDataBase.beginTransactionNonExclusive()`
 - `SQLiteDataBase.beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)`

beginTransactionNonExclusive/beginTransactionWithListenerNonExclusiveはAPI Level11で追加されたAPI.

beginTransaction/beginTransactionWithListenerで開始されたトランザクションはExclusive modeで, 
beginTransactionNonExclusive/beginTransactionWithListenerNonExclusiveで開始されたトランザクションはImmediate modeで動作する. 

```java
// Transaction Exclusive mode
db.beginTransaction();
try {
    // do something.
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

// Transaction Immediate mode
db.beginTransactionNonExclusive();
try {
    // do something.
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}
```


### SQLiteDatabaseLockedException

ロックされているデータベースに対し, SQLiteDatabase経由でクエリを実行した場合の挙動は下記. 

#### SQLiteDatabase.query

ロックが取得できるまでトランザクションは待機される. API Level16以降は[CancellationSignal](http://developer.android.com/reference/android/os/CancellationSignal.html)を使ってクエリをキャンセルすることができる. 


#### SQLiteDatabase.insert

SQLiteDatabaseがSQLiteDatabaseLockedExceptionをキャッチし, 呼出し元に-1を返す. 

```java
public long insert(String table, String nullColumnHack, ContentValues values) {
    try {
        return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
    } catch (SQLException e) {
        Log.e(TAG, "Error inserting " + values, e);
        return -1;
    }
}
```

#### SQLiteDatabase.insertOrThrow

SQLiteDatabaseLockedExceptionがスローされる. 

```java
public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
        throws SQLException {
    return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
}
```

#### SQLiteDatabase.update

SQLiteDatabaseLockedExceptionがスローされる. 

#### SQLiteDatabase.delete

SQLiteDatabaseLockedExceptionがスローされる. 

#### SQLiteDatabase.beginTransaction

SQLiteDatabaseLockedExceptionがスローされる. 


Reference
-------------------------------------------------------------
[File Locking And Concurrency In SQLite Version 3](http://www.sqlite.org/lockingv3.html)

以上. 


転記元: http://yuki312.blogspot.jp/2012/07/androidsqlitetransaction.html