TRANSACTION について

TRANSACTION はデータベースの排他制御を学ぶ上で大変重要な概念です。ここでは、本書で述べられている SET TRANSACTION について、いくつか補足したいと思います。

SET TRANSACTION のオプションとして本書では READ ONLY と READ WRITE を説明しています。本書では、話の流れ上、READ ONLYを指定した場合、他のユーザーが変更できなくなると明記されていますが、これはかなり大胆な記述でして、実際は他のユーザーの変更が反映されなくなるという意味です。
言い換えると、READ ONLY を使って TRANSACTION を開始した場合でも他のユーザーが別のセッションで現行ユーザーと同じ表を扱い、表の変更を行うことができます。
しかし、この変更は現行のユーザーには見えません。変更は、トランザクション終了後に反映することになります。
このように、1つのトランザクション中でデータが一意に保証されることを、一般にデータの一貫性が保たれるといいます。

なお、このような排他制御のレベルに関しては、各RDBMSによって仕様はさまざまです。一般に Dirty read や Repeatable read のように呼ばれ、いくつかのレベルに分割されます。
ここでは、ORACLEを例に解説しています。

下記に READ ONLY および READ WEITE オプションを指定した例を記述しました。
(注)を参考にして頂けると、どのような違いがあるのかはっきりとわかると思います。

TEST 表

ID  LANG   
1 JAPANESE

この表に対して、User1, User2 以下のが以下の処理を行うとします。ここでは、User1 が SET TRANSACTION の READ WRITE オプションを使っています。

処理の流れ User1の作業 User1 から見た TEST表の内容 User2 の作業
1 SET TRANSACTION READ WRITE; 1 JAPANESE
2 UPDATE TEST SET LANG = 'ENGLISH' WHERE ID = 1;
3 SELECT * FROM TEST; 1 JAPANESE
4 COMMIT;
5 SELECT * FROM TEST; 1 ENGLISH  (注1)

では、今度は User1 が SET TRANSACTION の READ ONLY オプションを使った例です。

処理の流れ User1の作業 User1 から見た TEST表の内容 User2 の作業
1 SET TRANSACTION READ ONLY; 1 JAPANESE
2 UPDATE TEST SET LANG = 'ENGLISH' WHERE ID = 1;
3 SELECT * FROM TEST; 1 JAPANESE
4 COMMIT;
5 SELECT * FROM TEST; 1 JAPANESE (注2)
6 UPDATE TEST SET LANG = 'SPANISH' WHERE ID = 1 ; (エラー) (注3)
7 COMMIT;
8 SELECT * FROM TEST; 1 ENGLISH (注4)

(注1) User2 が変更を行い COMMIT が発行されたのでその時点で User1 から見た場合も変更が反映されます。
(注2) User2 が変更を行い COMMIT が発行されましたが、READ ONLY でトランザクションが開始されているため、変更が反映されません。
(注3) READ ONLY でトランザクションが開始されているため、表データの変更はできません。
(注4) 上のCOMMIT によってトランザクションが終了していますので、User2の変更が反映されています。