misc.log

日常茶飯事とお仕事と

Repeatable Readって?

データベースとしてInformixを使ったシステムの処理を追いかけていて、分離レベル(Isolation Level)に「リピータブル モード」というのが出てきてちょっとつまってます……この辺、きちんと説明できない自分発見(わかってましたけど)。とりあえず、今のシステムをOracleへ移すにあたって「何なの?」はきちんと理解しておかないとやばいので、確認しましょう。

SQL-92 Isolation Levels/IBM Developer Works
http://www.ibm.com/developerworks/data/zones/informix/library/techarticle/db_isolevels.html

んぁぁ…さらに検索。

Informix テクニカル Q&A/Committed ReadとRepeatable Readの違いが分かる方法は?
http://www-06.ibm.com/software/jp/data/informix/support/tech/tech_a5.html#01
  • Committed Read(CR)は共有ロックをかけない
  • Repeatable Read(RR)は共有ロックをかける

ある処理で読み込みをかけた状態で、別セッションから更新を行うと、CRは更新できるが、RRはエラーになる。そういうことのようで。では、Oracle DBでRRと同じことをするにはどうすればいいのか。というか、まず「リピータブル」が何を指すかを考えよう。ここの説明が判りやすかった。

基礎から理解するデータベースのしくみ(11)/トランザクションとは何だろう(ITPro)
http://itpro.nikkeibp.co.jp/article/COLUMN/20060118/227489/

一度読んで、もう一度読んだ時に同じ値が返ってくる、これがリピータブル(反復可能)ということらしい。なるほど。それには読めるけど更新されないというロックを掛ける必要があるわけね。各ロックと構文についてもマトリクスとしてまとめられてて判りやすい。で、LOCK TABLEステートメントで実際に共有ロックを掛けるにはどうすればよいかは、ここを見れば書いてありました。

Oracle Database SQL言語リファレンス 11gリリース2(11.2)
http://docs.oracle.com/cd/E16338_01/server.112/b56299/statements_9015.htm

たぶんこれですね。

LOCK TABLE IN SHARE MODE;

で……ここで気づいた…。ODP.NETのConnectionオブジェクトが持つBeginTransactionメソッドの引数で、こんな指定が可能でした……

BeginTransaction(IsolationLevel.RepeatableRead)

なんだ最初からこれで終わりじゃん…(↓続く)

ダメです。Oracleは2つの分離レベルしかサポートしていません

上記の続き。BeginTransaction(IsolationLevel.RepeatableRead)は使えません。OracleのODP.NETヘルプをみると…

備考
分離レベルIsolationLevel.ReadCommittedおよびIsolationLevel.Serializableがサポートされています。
他の分離レベルを要求すると、例外が発生します。

あぁ、書いてありました。引数の指定に使っている列挙型は「System.Data.IsolationLevel」、これは.NETが標準的に持つ汎用の選択肢で、Oracleはこのうち2つしか利用を許していないと。さらには使えない選択肢を選ぶと例外がでるようです。なんてこった。
となると、Repeatable Readに相当するものはより厳しい「Serializable」か、他からの更新可能性がある「ReadCommitted」しかない…と。どちらを使うかは要件次第ってことですね。