このページをはてなブックマークに追加このページを含むはてなブックマーク このページをlivedoor クリップに追加このページを含むlivedoor クリップ

目次

トランザクション

  • トランザクションはアトミック性(成功か不成功かの2つに1つ)を持つため、トランザクションスコープに含まれているすべての処理が終わらないとトランザクションは終了しない。
  • アトミック性を持たせるために、一部が遅延するだけでユーザーへの結果表示が待たされることがある。よって、トランザクションは必要最小限の処理しか含まないようにしないと無駄が生まれる。

例:振込み処理において、振込先の増額と振込元の減額がセットに行わなければデータが不正になる。 ◇

トランザクションスコープ

  • トランザクションの開始から終了までの範囲(スコープ)のこと。
  • どの処理までを1つのトランザクションに含めるのかを既定する。

トランザクション管理

  • RDBMSは1つ1つのSQLを処理するだけなので、SQLの実行に失敗したときにどこまで戻すのかがわからない。どこまで戻すのかを指定するのは、SQLを発行するアプリケーション側の役割である。このために、SQLにはcommit,rollback(abort)などのトランザクションを表現する命令が用意されている。
  • SQLを発行するアプリケーション側の事故により、commitあるいはrollbackのどちらも発行していないトランザクションが発生してしまうことがある。
    • この場合は、RDBMSが未完のトランザクションを検出した時点で、強制的にrollbackを実行する。

トランザクション管理用の命令

rollback(abort)

  • トランザクションの途中で異常が起こり、処理が完了できなかったことをRDBMSに通知する。
  • RDBMS側はこの通知を受け取ると、DBの状態をトランザクションの開始時点まで巻き戻し、処理が何もなかったように見せる。

commit

  • トランザクションが正常に完了したことを通知する。
  • commitが発行したトランザクションの結果は、どのようなことがあっても失ってはならない。

begin

  • rollbackやcommitを発行すると、その後新しいトランザクションを開始する。
  • アプリケーションが最初にRDBMSに接続した時点で新しいトランザクションが始まることもある。
  • RDBMSによっては明示的にトランザクションを始めるためにbeginを用意していることもある。

各種SQLにおけるトランザクション管理

MySQL

  • MySQLデータベースでは、テーブルの型によってはトランザクションが利用できない。
    • 一般にはInnoDB型が使われる。
  • BEGIN命令によってトランザクションが開始される。
  • COMMIT命令を実行すると変更が確定する。
    • BEGINとCOMMITの間にINSERT,UPDATE,DELETE命令が行われる。
  • ROLLBACK命令により変更が元に戻る。
    • TRUNCATE,DROP DATABASE/TABLE命令などの場合、命令実行後に変更が確定するので、ロールバックできないことに注意。

トランザクションの分割

  • 大量データのバッチ処理において、トランザクションの原則の1つである原子性を磨耗路として、1つのトランザクションが長くなってしまった結果、DBMSのリソースを使い切ってエラーになってしまう場合がある。
    • OracleにおけるORA-1555
  • 処理できない(エラーが起こる)ようなサイズのトランザクションは適切に分割しなければならない。
    • トランザクションを分割するとエラー時の再実行が難しくなる。データパッチを行って再実行可能にしたり、SEが手動でエラー以降の処理を実行する。
  • トランザクションを分割していないことの典型的な原因は次の通りである。
    • バッチ処理の分割のポリシーが決まっていない。もしくは分割しないポリシーである。
    • 大量データを用いたバッチ処理の試験をしていない。
    • リソースの容量監視をしていない。

トランザクションをまとめる

  • DBMSのリソースに余裕があるにもかかわらず、不用意にコミットを実行してトランザクションを分割してしまっている場合は、トランザクションを1つにまとめた方がよい。
  • 不用意にAutoCommit機能を有効にすることで、SQLごとにコミットされてしまう。
    • つまり、業務から見た最適なトランザクションの単位(処理の単位)かどうかに関わらず、各SQLごとに子もっとされてしまう。

トランザクションの独立性レベル

  • トランザクションの独立性を高くすると、同時に実行できるトランザクションの数が減少する。
  • 独立性と並列性のバランスを確保するために、トランザクションの独立性レベル(隔離性レベル)が定められている。

各独立性レベル

独立性レベル内容
READ UNCOMMITEDコミットされていない行を読み込んでもよい。
READ COMMITEDコミットされた行を読み込むものとする。読み出した行は他のトランザクションが更新してもい。
REPEATABLE READ繰り返し読み込み可能とする。読み出した行は他のトランザクションが更新することはないが、他のトランザクションによる追加行を読み込む場合がある。
SERIALIZABLE直列可能性を保証する。逐次実行と同一の結果になる。
  • 最も高い独立性はSERIALIZABLEである。
    • このとき、複数のトランザクションを実行した場合であっても、逐次実行した結果と同一になる。

独立性レベルと発生する現象

 その他のレベルを設定した場合には次の現象が発生する可能性がある。

独立性レベルダーティリードノンリピータブルリードファントム
READ UNCOMMITEDありありあり
READ COMMITEDなしなしあり
REPEATABLE READなしなしあり
SERIALIZABLEなしなしなし

SQLによる独立性レベルの設定

 SQLで独立性レベルを設定するには、SET TRANSACTION文を使う。

例:

SET TRANSACTION READ UNCOMMITED

 独立性レベルを指定しないこともできる。SERIALIZABLE設定をすれば、何も設定しないことと同じになる。

例:

SET TRANSACTION READ SERIALIZABLE

参考文献

  • 『RDBMS解剖学』
  • 『情報処理技術者試験ポケットスタディ 応用情報技術者』
  • 『情報処理技術者試験 やさしく学ぶデータベース技術』
  • 『DB SELECTION 44のアンチパターンに学ぶDBシステム』