2019/4/20 部分改訂
========================================================-
0.はじめに
前々回の投稿「CPU使用率100%は悪なのか?」につきましては、本当に多くの方々に読んでもらったようで大変ありがとうございます。改めて御礼申し上げます。前回の投稿からだいぶ時間がたってしまいましたが、今回は「トランザクション」とは何か?をお話ししたいと思います。
#1. 「トランザクション」とは?
「トランザクション」と言うと、単純に商業的な「取引」を連想する方もいらっしゃるかと思いますが、ここでは、IT用語としての「トランザクション」を採り上げます。この用語は、例えば設計や実装をするときばかりでなく、テストを実施したり、パフォーマンスを評価したりする際に必ず1度は聞く用語かと思います。他方、「そもそも『トランザクション』って何?」と聞かれた場合、どのように連想しますでしょうか?「とりあえず、複数の処理を1つにまとめたものかな?」といった漠然としたイメージは持つかもしれません。そうです。「トランザクション」とは複数の処理を1つにまとめたものです。
他方、その「複数の処理」について、「そもそもなんで複数の処理をわざわざ1個にしているわけ?」「別に1個にしなくても分けてしまうのもありなのでは?」という意見もあるかもしれません。果たして「複数の処理」というのは切り離すことはできるのでしょうか?これを踏まえて、筆者なりに「トランザクション」を以下のように定義できると思います。
- 複数の処理を1つにまとめたもの。
- ただし、これら「複数の処理」は分離させることはできない。
#2. 「トランザクション」の例
更に理解を更に深めてもらうため、例を挙げたいと思います。「トランザクション」の例と言うと、やはり銀行の口座振込みですよね。ここでは、Aさんの口座(残高:10,000円)から5,000円、Bさんの口座(残高:20,000円)へ振り込むケースを考えます。これは以下の処理から構成されます。
######1. Aさんの口座から5,000円分差し引き、残高10,000 - 5,000 = 5,000円にする。
######2. Bさんの口座へ5,000円分プラスし、残高20,000 + 5,000 = 25,000円にする。
ここで、これら2つの処理を分離する、言い換えると2.の処理を別の「トランザクション」として新たに独立させたとします。そうしたらどうなりますでしょうか?
1.の処理がうまくいって、2.の処理が何らかの原因で失敗したとします。そうなると、Aさんの口座残高は5,000円になっているいる一方で、Bさんの口座残高は20,000円のままで、5000円が「消失」してしまうことになります。
見方を変えると、1.の処理と2.の処理をまとめて「1つの処理」として扱うことにより、仮に1.がうまくいって2.がうまくいかなかったとしても、この「1つの処理」としては失敗したことになるので、最初からなかったことにすることで5000円が消失してしまうのを避けることができるというわけです。この「1つの処理」とは「トランザクション」を指すことはご理解いただけるかと思います。
#3. 「トランザクション」は成功か失敗のいずれかである。
ここまで来るともしかしたらピンとくるかもしれませんが、「トランザクション」は成功か失敗かのどれかしかありません。失敗した場合は「トランザクション」実行前に戻ります。中途半端に成功したとか中途半端に失敗したとか、そういうことは絶対にありません。「トランザクションのACID特性」という言葉を聞いたことがある方もいると思いますが、そのうちのA (Atomicity)、つまり「原子性」に該当します。上記の振込みの例で言うと、「トランザクション」を実行した結果、以下のいずれかの結果にしかなりません(※1)。
- Aさんの口座残高は5,000円になり、Bさんの口座残高は25,000円になった。(トランザクション成功)
- Aさんの口座残高は10,000円、Bさんの口座残高は20,000円で金額に変動はなかった。(トランザクション失敗)
振込み処理とは普通、1回の振込みにより、振込金額分だけ振込元の口座残高から差し引かれ、振込先の口座残高がプラスになるものです。この「1回の振込み」がたとえ複数個の小さな処理に細分化されたとしても、そのうちのどこかで失敗したら全て失敗、振込み前に戻るという扱いになります。なぜなら、繰り返し述べているように、Aさんの口座からは5000円引かれているのにBさんの口座には5000円入金されていない、という中途半端な結果にしてはいけないためです。そうです!結果の整合性が求められる処理については、仮にその処理が複数個の細分化された処理に分かれたとしても、これらは1個の「トランザクション」としてまとめる必要があるのです。
#4. 「トランザクション」のまとめ
ここまで来ると、「トランザクション」とは何か?について、イメージはつかめたのではないかと思います。このように、「トランザクション」は以下のようにまとめられるでしょう。
- 結果の整合性が要求される、複数の処理を1つにまとめたもの。
- ただし、これら「複数の処理」は分離させることはできない。
- 実行した結果は、成功か失敗のいずれかである。
実際「トランザクション」とは奥が深いものです。本稿は、あくまでその一部に触れたにすぎませんが、読者の方々にとって「トランザクション」をマスターするためのとっかかりとして寄与できればこれに越したことはありません。ここまで読んでくださりありがとうございました。
#脚注
(※1) 絵にも載せていますが、正確に言うと、「トランザクション」の中の一連の処理が全て成功したのち「コミット」することで処理内容を反映させます。一方で、「トランザクション」の中の一連の処理のうち、どこかがうまくいかなかったら「ロールバック」することで「トランザクション」実行前の状態に戻ります。「コミット」、「ロールバック」含めたトランザクション機能は、DBMSやアプリケーションサーバ等の多くの製品で搭載されています。