- 11.1. トランザクションの特性
- 11.2. コミットとロールバック
- 11.3. トランザクションの構文
- 11.4. 排他制御
- 11.5. ロック
- 11.6. トランザクションの定義
11.6. トランザクションの定義
ここでいうトランザクションの定義とは、SET TRANSACTION 文を用いて、次の項目について設定を行うということです。
- アクセスモード
- トランザクションが読み取り専用であるのか、読み取り / 書き込み可能なのかを指定します。初期値は READ WRITE(読み取り / 書き込み可能) です。
- 隔離レベル
- ACID 特性の隔離性 (ISOLATION) のレベルを指定します。初期値は READ COMMITTED です。
- 診断域
- SQL 文の処理結果に関する情報を格納する領域を指定します。
トランザクションは、暗黙的に開始された場合でも、明示的に開始された場合でも、SET TRANSACTION 文により上記 3つの項目について設定を行わなかった場合は、それぞれの初期値で実行されます。
SQL92 における SET TRANSACTION の基本構文は次の通りです。
SET TRANSACTION
[ {READ ONLY | READ WRITE} ]
[ ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED |
REPEATABLE READ | SERIALIZABLE}]
[ DIAGNOSTICS SIZE 行数 ] ;
この基本構文のそれぞれの項目について説明します。
アクセスモードは READ ONLY 句または READ WRITE 句で指定します。
READ ONLY | 読み取り専用 |
READ WRITE | 読み書き両用(初期値) |
READ ONLY 句を指定すると、そのトランザクションは読み取り専用モードになります。このトランザクションで SELECT 文を実行すると、トランザクション開始前の状態のデータを参照することができます。このトランザクション実行中に他のトランザクションでデータに変更が加えられても、その前の状態のデータを参照できるということです。
READ WRITE 句を指定すると、そのトランザクションは読み書き両用モードになります。このトランザクションでは INSERT 文、UPDATE 文及び DELETE 文を使用してデータを変更することができます。このトランザクションで SELECT 文を実行すると、他のトランザクションによるデータの変更も参照することができます。
隔離レベルは、READ UNCOMMITTED 句、READ COMMITTED 句、REPEATABLE READ 句または SERIALIZABLE 句で指定します。
READ UNCOMMITTED | 共有ロック、排他ロックも使用されない、最も隔離性の緩やかなレベルです。ダーティリード、ノンリピータブルリード、ファントムインサートが発生する可能性があります。 |
READ COMMITTED | トランザクションが開始されて、まだコミットされていない場合には、他のトランザクションからはデータを参照することができないレベルです。従って、ダーティリードは発生しません。しかし、他のトランザクションによりデータの変更は可能なため、ノンリピータブルリード、ファントムインサートが発生する可能性があります。 |
REPEATABLE READ | トランザクションが完了するまで共有ロックが継続されるので、一度読み取ったデータが他のトランザクションによって変更されることはありません。ファントムインサートが発生する可能性があります。 |
SERIALIZABLE | 他のトランザクションからは完全に隔離したレベルで、他のトランザクションの影響を一切うけません。トランザクション実行中に、他のトランザクションがアクセスしても、そのトランザクションは待機状態になり、前のトランザクションが終了するまでデータにアクセスすることができません。 |
隔離レベルについては表に示す通りですが、複数のトランザクションが同じデータにアクセスすることにより、発生する問題が 4つあります。それは、ロストアップデート、ダーティリード、ノンリピータブルリード及びファントムインサートという現象で、次の表にその説明を示します。
ロストアップデート | あるトランザクションで変更した値が、他のトランザクションにより別の値に変更されてしまうこと。 |
ダーティリード | 他のトランザクションがデータの変更を取り消したにも関わらず、取り消し前にそのデータを読み出してしまうこと。 |
ノンリピータブルリード | あるトランザクションにおいて、同じ行を 2 回読み込んだときに、1 回目と 2 回目の読み込みの間に、他のトランザクションが行の値の変更を行ったために、1 回目と 2 回目で読み込んだデータの値が異なってしまうこと。 |
ファントムインサート | あるトランザクションにおいて、WHERE 句等による同じ条件により行を読み込んだときに、その途中に他のトランザクションがその条件に影響を与える行の挿入を行ったために、先に読み込んだ行と後に読み込んだ行が異なってしまうこと。 |
それぞれ、例をあげて説明します。ここでは、テーブル名 TableA、TableA の列 ColA を例に説明します。
TransactionA と TransactionB が、ColA=10 であることを確認した後に、TransactionA が ColA の値を 10 から 8 に変更します。しかし、その直後に TransactionB が ColA の値を 15 に変更してしまうと、TransactionA の行ったデータの更新はデータに反映されなかったことになります。このような現象をロストアップデートといいます。
TransactionA が TableA の ColA の値を最初に確認した後に、UPDATE 文で ColA の値を 10 から 15 に変更します。この後で、TransactionB は ColA の値を読み取ります。その後、TransactionA が変更処理を ROLLBACK 文で変更してしまったとき、TransactionB の読み取った値は、確定されなかったものになってしまいます。このような現象をダーティリードといいます。
TransactionB が ColA の値を読み取った後で、TransactionA が ColA の値を 10 から 15 に変更し、その後、TransactionB が再び ColA の値を読み取ると、TransactionB は同じ行に対して 1 回目と 2 回目で異なる値を読み取ってしまうことになります。このような現象をノンリピータブルリードといいます。
TransactionB が TableA の ColA 列の値の平均を読み取った後で、TransactionA が行を追加し、その後、TransactionB が再び TableA の ColA 列の値の平均を読み取ろうとすると、TransactionB は以前と異なる値を読み取ってしまうことになります。このような現象をファントムインサートといいます。
最後に、トランザクションの隔離レベルと隔離性に関する問題の関係をまとめた表を示します。表中の×は起こりうることを意味します。
隔離レベル | ロスト アップデート |
ダーティリード | ノンリピータ ブルリード |
ファントム インサート |
---|---|---|---|---|
READ UNCOMMITTED | × | × | × | |
READ COMMITTED | × | × | ||
REPEATABLE READ | × | |||
SERIALIZE |
実習課題 1
次の表と関係のある隔離性問題とは何か? 隔離性問題とは、ロストアップデート、ダーティリード、ノンリピータブルリード、ファントムインサートのことである。
Transaction 1 | Transaction 2 |
---|---|
select avg(option_price) from accept_order; |
|
update accept_order set option_price = 5 where o_num = '1004'; |
|
select avg(option_price) from accept_order; |
実習課題 2
次の表と関係のある隔離性問題とは何か? 隔離性問題とは、ロストアップデート、ダーティリード、ノンリピータブルリード、ファントムインサートのことである。
Transaction 1 | Transaction 2 |
---|---|
select avg(option_price) from accept_order ; |
|
insert into accept_order values('1020', '1004', '104' , 30 , 100 , '102' , '2001-04-01' ); |
|
select avg(option_price) from accept_order ; |