Image
Top
Navigation

トランザクション分離レベルについての確認 Fuzzy Read

ダーティリードの次はファジーリード(Nonrepeatable Read / Fuzzy Read)を確認します。

OrientDBは1.7.8の段階ではレベルをIsolation Level を REPEATABLE READとしています。

実際に確認していきたいと思います。
手順としては前回と一緒のリモート接続にてJavaのAPIを使用して実施します。

ファジーリード

まずはファジーリードとはの確認。別のトランザクションで更新後データを読むことにより、一貫性がなくなる現象のことです。

今回の確認の手順としては、

1.トランザクションAでレコードをSELECTする。「未処理」となっている。
2.トランザクションBでレコードを「未処理」から「トランザクションB」にUPDATEし、COMMITする。
3.トランザクションAで同じレコードを再度SELECTする。「トランザクションB」となっている。

今回も2つの非常にシンプルなJavaプログラムを使用します。
一つは、トランザクションA用のプログラム.

package transaction.fuzzyread;

import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.tx.OTransaction.TXTYPE;

public class Transaction_lock5Stop {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ODatabaseDocumentTx database = null;
        try {

            System.out.println(">>>> トランザクションA");
            // remoteでデータベースへ接続します。

            database = new ODatabaseDocumentTx("remote:172.16.251.205/DocumentTest");
            database.open("root", "root");

            database.begin(TXTYPE.OPTIMISTIC);

            // RIDを指定して直接取得
            ODocument doc_ = database.load(new ORecordId("#26:0")).getRecord();

            // save前に値を確認
            System.out.println("> トランザクショの中で取得");
            for (String fieldName : doc_.fieldNames()) {
                System.out.println(fieldName + " : " + doc_.field(fieldName));
            }

            // 10秒Sleepする.この間にトランザクションBを実行する
            System.out.println("---------- 10秒Sleepする ----------");
            Thread.sleep(10000);


            System.out.println("> 同一トランザクショの中で再取得");
            ODocument doc_3 = database.load(new ORecordId("#26:0")).getRecord();

            for (String fieldName : doc_3.fieldNames()) {
                System.out.println(fieldName + " : " + doc_3.field(fieldName));
            }


            database.close();

        } catch (Exception e) {
            e.printStackTrace();
            database.rollback();

        } finally {

            database.close();
        }

    }
}

内容としては、トランザクションを開始後、RIDが#26:0のstatusフィールドの値「処理前」を取得し10秒ほどスリープします。
その間にトランザクション2を実行するためです。
トランザクション2の更新が完了したあとに同一トランザクション内で再度RIDが#26:0の値を取得し、トランザクション2からの影響が発生していないか確認します。

こちらは、トランザクションB用のプログラム.

package transaction.fuzzyread;

import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.tx.OTransaction.TXTYPE;

public class Transaction_lock5 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ODatabaseDocumentTx database = null;
        try {
            System.out.println(">>>> トランザクションB");
            // remoteでデータベースへ接続します。

            database = new ODatabaseDocumentTx("remote:172.16.251.205/DocumentTest");
            database.open("root", "root");

            database.begin(TXTYPE.OPTIMISTIC);

            // RIDを指定して直接取得
            ODocument doc_ = database.load(new ORecordId("#26:0")).getRecord();

            // save前に値を確認
            System.out.println("> save前に値を確認");
            for (String fieldName : doc_.fieldNames()) {
                System.out.println(fieldName + " : " + doc_.field(fieldName));
            }

            // 更新します
            doc_.field("status", "トランザクションB");
            doc_.save();

            // save 後の値を確認
            System.out.println("> save 後の値を確認");
            ODocument doc_2 = database.load(new ORecordId("#26:0")).getRecord();

            for (String fieldName : doc_2.fieldNames()) {
                System.out.println(fieldName + " : " + doc_2.field(fieldName));
            }

            database.commit();

            database.close();

        } catch (Exception e) {
            e.printStackTrace();
            database.rollback();

        } finally {

            database.close();
        }

    }
}

こちらの内容としては、RIDが#26:0の値を取得し「status」の値を「トランザクションB」へ更新しコミットはします。
確認のために、レコード取得後、更新後に値を表示しています。

こちらはAの結果です。

>>>> トランザクションA
> トランザクショの中で取得
name : IsolationTest
status : 処理前
---------- 10秒Sleepする ----------
> 同一トランザクショの中で再取得
name : IsolationTest
status : 処理前

こちらはBの結果です。

>>>>トランザクションB
> トランザクションAがスリープの間に値を取得
name : IsolationTest
status : 処理前
---------- 10秒Sleepする ----------
> 値を更新してコミット
name : IsolationTest
status : トランザクションB

トランザクションA内の値が、トランザクションBのコミット前後の値には影響を受けずに値を表示できています。
これで、Documentデータベースはファジーリードが発生していないことが確認できます。

次にグラフデータベースで確認をしてみましょう。

次は、パンファムリードに関して試していきたいと思います。