同一データへの同時書き込みを防止する機能を「ロック」といいます。Oracle Serverの場合は、デフォルトで行単位にロックをかけます。また、指定すれば表単位でかけることもできます。 SQL Serverでは、特に指定しない限り最適なロックが選択されますが、基本的には「行ロック」や「キーロック(インデックス内の1行に対してかかるロック)」が使用されます。また、「ロックのエスカレーション」という機能があり、あるトランザクションで保持するロック数がしきい値を越えると、行ロック、キーロック、「ページロック」を自動的に「テーブルロック」に拡大します。ロックの単位を大きくすると同時実効性は低くなりますが、反対にロックによるオーバーヘッドを減少させることができます。
SELECT文を実行すると、その時点でのコミット済みのデータを戻すしくみを、「読み取り一貫性」といいます。Oracle Serverでは、「UNDOセグメント」を使用して読み取り一貫性を実現しています。UNDOセグメントには変更前のコミット済みのデータが格納されています。 SQL Serverには、UNDOセグメントに相当するものはありません。読み取り一貫性を保証するために、ロックメカニズムが使用されています。デフォルトではSELECT文でもロックがかかり、コミット前のデータに対してSELECT文が実行された場合、ダーティデータを読むのを防ぐために待ちの状態になります。SQL Serverでは、このようなロックメカニズムを意識したSQL文の記述が重要になります。 ☆さらに詳細はこちら→
Oracle Serverのトランザクションは「INSERT」などの特定のステートメントで開始し、「COMMIT」で確定、「ROLLBACK」で取り消します。 SQL Serverの場合は、開始、終了の仕方が次の3通りあります。
1:自動コミット 既定では、1つのSQLステートメントは1つのトランザクションです。ステートメントが正常終了すると自動でCOMMITまで済んでしまいます。 2:明示的トランザクション 既定のセッション状態で「BEGIN TRANSACTION」と明記すると、そこでトランザクションが始まります。「COMMIT TRANSACTION」で確定し、「ROLLBACK TRANSACTION」で取り消します。これがもっとも一般的なトランザクションの扱い方です。 3:暗黙的トランザクション セッションの「IMPLICIT_TRANSACTIONSオプション」をONにすると、「BEGIN TRANSACTION」と明記しなくても、INSERTなどの特定のステートメントでトランザクションが開始します。終了の仕方は明示的トランザクションと同様です。
Oracle Serverでは、2人以上のユーザーが相互に相手がロックしているデータを待機しようとした場合に、「デッドロック」が発生します。SQL Serverでもこれは同様ですが、もう一つSQL Server特有のデッドロックとして「変換デッドロック」というものがあります。 変換デッドロックは、SQL ServerのSELECTで発生する「共有ロック」というタイプのロックによって起こります。たとえば、2人のユーザー(A子、B子)が、それぞれのトランザクションで同じテーブルの同じデータをSELECT→UPDATEしようとしています。既定では、共有ロックはSELECT後すぐに解除されますが、共有ロックがかかり続けるような特殊なセッション状態にしていたとしましょう。その状態でA子がSELECT後、B子がSELECTします。1つのリソースに2つの共有ロックがかかり続けているところで、A子がUPDATEしようとするとB子のロックに待たされます。ここでB子がUPDATEしようとするとデッドロックが発生します。これが変換デッドロックです。なお、これは共有ロックの仕組みを持つDB2でも発生します。デッドロックは、OracleでもSQL Serverでもシステムによって自動的に検出され、一部のロックが解放されます。
「トランザクション分離レベル」を変更すると、ロックの保持期間などを制御することができます。変更の構文は、Oracle ServerもSQL Serverも「SET TRANSACTION ISOLATION LEVEL」を使用します。トランザクション分離レベルの種類は、Oracle Serverでは「READ ONLY」、「READ COMMITTED(既定)」、「SERIALIZABLE」の3種、SQL Serverではセッションレベルで以下の4種を設定できます。
1「READ UNCOMMITTED」 SELECT時に共有ロックがかかりません。 2「READ COMMITTED(既定)」 データが読み取られている間、共有ロックが保持されます。 3「REPEATABLE READ」 SELECTの共有ロックはトランザクション終了まで保持されます。 4「SERIALIZABLE」 SELECTで読み込んだキー範囲の共有ロックがトランザクション終了まで保持されます。
READ UNCOMMITTEDは、ダーティリードが起きるのでデータ精度は低いですが、同時実行性が上がります。REPEATABLE READとSERIALIZABLEは、データ精度が上がりますが同時実行性が下がります。
「セーブポイント」を使用すると、トランザクション内を複数の論理的なセクションに分割し、そしてセーブポイント付きのロールバックステートメントを実行することでトランザクション内の特定DMLをロールバックすることができます。Oracle ServerもSQL Serverも、ほぼ同等のセーブポイント機能を実装しています。 SQL Serverでセーブポイントを使う場合、まず「BEGIN TRANSACTION」ステートメントで明示的にトランザクションを開始し、「SAVE TRANSACTION セーブポイント名」ステートメントでセーブポイント設定します。セーブポイント名は32文字以内まで使用可能です。トランザクションを取り消すときは、「ROLLBACK TRANSACTION セーブポイント名」ステートメントを使用します。