WEB+DB PRESS Vol.58はでかでかとRails 3と特集が組まれ、Rails関連者にはもはや必須となっている感があります。
![WEB+DB PRESS Vol.58]()
WEB+DB PRESS Vol.58
編
しかしながら、Railsでは冷やかししかできない私は、しずしずとミックさんの連載「DBアタマアカデミー」を読み解くのでした。さすがにミックさん、うまくまとめていらっしゃる。軽快、明白な説明に納得です。トランザクションの入門に、是非参照してみてください。
しかしながら、トランザクションは各DB実装毎に考え方が違い、有る意味「実装の闇」でもある部分です。そのため概論では、これで十分ですが、いくつか「闇」部分も勝手に補足いたします。
(1) 表1 DBMS別トランザクション開始/終了コマンド
PostgreSQLはBEGIN WORKも開始コマンドとして使えます。
またMySQLはBEGINのみとBEGIN WORKでも開始することができます。つまり、BEGIN WORKはPostgreSQLとMySQLで使えるということになります。
(2) いい加減であることの代償は?
P0: ダーティライト
P4: ロストアップデート
というのもありますよー。というのをこっそり補足。
詳細は以下のエントリと、そこからのリンクを参照のこと。
失われた更新(Lost Update)
(3) 表4 DBMSと分離レベルの対応
ここが一番悩ましいところ、ですが、明確なところから補足。
(a) MySQL(InnoDB)のデフォルト値が違う
表ではMySQL(InnoDB) コミット読み取り(READ COMMITTED)がデフォルト◎になっていますが、正しくは再読込可能読み取り(REPEATABLE READ)です。もしくは、mysqlサーバ起動時に--ansiオプションを指定することにより、直列化可能(SERIALIZABLE)で起動します。いずれにせよ、コミット読み取りではありません。
(b) Oracleには再読込可能読み取り(REPEATABLE READ)はない?
Oracleはコミット済み読み取りと直列化可能しかないと、よく言われますが、実は微妙な立ち位置でREPEATABLE READが実装されています。それがREAD ONLYです。READ ONLYでは当然INSERT/UPDATE/DELETEはできませんが、動作としてはREPEATABLE READと同様にトランザクション開始時の値を何度も読みとることができます。この点で△にして、表に入れてもよいと思います。
こことか、後述するSQL Serverのドキュメントがわかりやすいです。
(3) DB2の名称がANSIと違いわかりにくい〜
これはミックさんのせいではありませんし、ミックさんの記述で正しいのですが、DB2のトランザクションとマップしようとすると混乱します。まぁ
以下のドキュメントを見てください。
DB2: 分離レベルの指定方法について
ざっくりいうと以下のようになります。
ISO DB2
SERIALIZABLE REPEATABLE READ(RR)
REPEATABLE READ READ STABILITY(RS)
READ COMMITTED CURSOR STABILITY(CS), CURRENTLY COMMITTED
READ UNCOMMITTED UNCOMMITTED READ(UR)
しかしながら、先ほど参照したIBMの資料にもあるように、省略形で指定する
場合の違いもあるので、IBM DB2では間違いないように省略形で指定するほうがよいでしょう。例えばISOでいうところのSERIALIZABLEを指定するのに、
DB2の用語ではREPEATABLE READ(RR)ですが、以下の分離レベルのところには
"RR", "SERIALIZABLE"または"REPEATABLE READ"が指定できます。
SET CURRENT ISOLATION 分離レベル
そして、現在の設定値を知るためのコマンドではRRが戻ってくるためです。
values current isolation
密かに上記の表ではCURRENTLY COMMITTEDを追加していますが、これは(4)
でまとめて説明します。
(4) コミット読み取り(READ COMMITTED)の全ての道はOracleに通じる
もともとMS SQL ServerとIBM DB2のコミット読み取り(READ COMMITTED)
の動作(主にロック関連)はOracleのものとは違っていました。それぞれOracleからの互換性、つまりOracleからのそれぞれのデータベースへの移行をスムーズにするために新しいモードを生成しました。
MS SQL Serverの場合はREAD_COMMITTED_SNAPSHOTというパラメタで
IBM DB2の場合はCUR_COMMITというパラメタで既存の動作と、新しい動作を切り替えることができます。
トランザクションとロックは各データベース毎に違いがありますので、まずはご自分が使われているデータベースの仕組みをしっかり押さえてから、他のデータベースを参照するとよいでしょう。
えっとミックさんが触れてくれないFirebirdについては、次回勝手に補足いたします(笑)
PlanetMySQL Voting: Vote UP / Vote DOWN

WEB+DB PRESS Vol.58
編
しかしながら、Railsでは冷やかししかできない私は、しずしずとミックさんの連載「DBアタマアカデミー」を読み解くのでした。さすがにミックさん、うまくまとめていらっしゃる。軽快、明白な説明に納得です。トランザクションの入門に、是非参照してみてください。
しかしながら、トランザクションは各DB実装毎に考え方が違い、有る意味「実装の闇」でもある部分です。そのため概論では、これで十分ですが、いくつか「闇」部分も勝手に補足いたします。
(1) 表1 DBMS別トランザクション開始/終了コマンド
PostgreSQLはBEGIN WORKも開始コマンドとして使えます。
またMySQLはBEGINのみとBEGIN WORKでも開始することができます。つまり、BEGIN WORKはPostgreSQLとMySQLで使えるということになります。
(2) いい加減であることの代償は?
P0: ダーティライト
P4: ロストアップデート
というのもありますよー。というのをこっそり補足。
詳細は以下のエントリと、そこからのリンクを参照のこと。
失われた更新(Lost Update)
(3) 表4 DBMSと分離レベルの対応
ここが一番悩ましいところ、ですが、明確なところから補足。
(a) MySQL(InnoDB)のデフォルト値が違う
表ではMySQL(InnoDB) コミット読み取り(READ COMMITTED)がデフォルト◎になっていますが、正しくは再読込可能読み取り(REPEATABLE READ)です。もしくは、mysqlサーバ起動時に--ansiオプションを指定することにより、直列化可能(SERIALIZABLE)で起動します。いずれにせよ、コミット読み取りではありません。
(b) Oracleには再読込可能読み取り(REPEATABLE READ)はない?
Oracleはコミット済み読み取りと直列化可能しかないと、よく言われますが、実は微妙な立ち位置でREPEATABLE READが実装されています。それがREAD ONLYです。READ ONLYでは当然INSERT/UPDATE/DELETEはできませんが、動作としてはREPEATABLE READと同様にトランザクション開始時の値を何度も読みとることができます。この点で△にして、表に入れてもよいと思います。
こことか、後述するSQL Serverのドキュメントがわかりやすいです。
(3) DB2の名称がANSIと違いわかりにくい〜
これはミックさんのせいではありませんし、ミックさんの記述で正しいのですが、DB2のトランザクションとマップしようとすると混乱します。まぁ
以下のドキュメントを見てください。
DB2: 分離レベルの指定方法について
ざっくりいうと以下のようになります。
ISO DB2
SERIALIZABLE REPEATABLE READ(RR)
REPEATABLE READ READ STABILITY(RS)
READ COMMITTED CURSOR STABILITY(CS), CURRENTLY COMMITTED
READ UNCOMMITTED UNCOMMITTED READ(UR)
しかしながら、先ほど参照したIBMの資料にもあるように、省略形で指定する
場合の違いもあるので、IBM DB2では間違いないように省略形で指定するほうがよいでしょう。例えばISOでいうところのSERIALIZABLEを指定するのに、
DB2の用語ではREPEATABLE READ(RR)ですが、以下の分離レベルのところには
"RR", "SERIALIZABLE"または"REPEATABLE READ"が指定できます。
SET CURRENT ISOLATION 分離レベル
そして、現在の設定値を知るためのコマンドではRRが戻ってくるためです。
values current isolation
密かに上記の表ではCURRENTLY COMMITTEDを追加していますが、これは(4)
でまとめて説明します。
(4) コミット読み取り(READ COMMITTED)の全ての道はOracleに通じる
もともとMS SQL ServerとIBM DB2のコミット読み取り(READ COMMITTED)
の動作(主にロック関連)はOracleのものとは違っていました。それぞれOracleからの互換性、つまりOracleからのそれぞれのデータベースへの移行をスムーズにするために新しいモードを生成しました。
MS SQL Serverの場合はREAD_COMMITTED_SNAPSHOTというパラメタで
IBM DB2の場合はCUR_COMMITというパラメタで既存の動作と、新しい動作を切り替えることができます。
トランザクションとロックは各データベース毎に違いがありますので、まずはご自分が使われているデータベースの仕組みをしっかり押さえてから、他のデータベースを参照するとよいでしょう。
えっとミックさんが触れてくれないFirebirdについては、次回勝手に補足いたします(笑)
PlanetMySQL Voting: Vote UP / Vote DOWN