過去と今のコミュニケーション

また久しぶりにデータベースの話をしたいと思います。前回は「論理削除か物理削除か」というテーマで記事を書いたらそこそこ反響がありました。こういったテーマは実際にDB設計に関わっている方でないと刺さらないのだと思いますが、そのうち入門者向けの話題も提供したいと考えています。

IDの採番方式

さて本題ですが、今回はIDの採番において私が実際に遭遇したトラブルについての話です。そもそも採番という言葉が一般的ではないのかなと思っていますが。というのも普通にPCで「さいばん」と打っても変換されないので、新しい現場へ行ってPCが貸与されると大抵この単語を辞書登録するからです。英語で言うと numbering が近いのでしょうか。別の言い方をすると発番あるいは番号の払出しといったところでしょうか。

利用するDBMS製品によってはIDの列に自動採番の属性を付与することで済ませるケースもありますが、多少癖もあるので緻密な運用を行いたい場合は自前で実装することになります。実装と言ってもそんなに難しいことはなく、IDが連番であることを利用してその最大値に1を足したものを新しいIDとするだけなのですが、その方式によっては注意が必要です。

これは設計者の好みの問題もあるのですが、テーブルの行数を見積もった時に、まあ普通に取り扱える規模であれば毎回最大値を計算して1を加算しても大した負荷にならないので私はその方式を良く使っています。一方で最大値を計算するのが負荷となるほどの行数が見込まれる場合は、本テーブルの他に最大値を管理する採番用テーブルを作ってそこで管理するケースがあります。

ちぐはぐなロジック

ある現場でデータの移行を実施した時のことです。ファイルに用意したデータ件数と、実際に取り込まれたデータの件数が1件だけ異なるという事故が起きました。あまり細かい話をしてもしょうがないのでざっくり書くと、そのシステムはWEBアプリケーションで、移行はバッチアプリケーションでしたが、両社でIDの採番方式が異なっていたためにWEBアプリで作られたデータを1件バッチで上書きしてしまっていたということが判明しました。

具体的には、WEB側では、採番用テーブルのIDに1足した番号を新しいIDとして本テーブルのレコードを作成し、その番号で採番用テーブルのIDを更新していたのですが、一方のバッチ側では、採番用テーブルのIDを使って本テーブルのレコードを作成し、そのID+1の番号で採番用テーブルのIDを更新していたのです。つまり採番用テーブルの番号が「使っている値の最大」なのか「次に使うべき値」なのかという解釈において相違があったわけです。

例えば、WEB側でIDが1~5までのデータが作成されていたとします。そこへ移行バッチでデータを追加すると本当は次のレコードのIDは6番でなければいけないのですが、採番用テーブルのIDが5番であるために追加するレコードのIDを5番としてしまい、すると結果的に既にある5番のデータが上書きされてしまうという事象が発生してしまいました。

鍵はコミュニケーション

この話の留意点は、どっちの方式が正しいかという議論ではないというところです。よくありがちなコミュニケーション不足、検討不足の症例です。要はどちらかのやり方にもう一方が合わせていれば全く問題の無かった話です。

また、これが実際に起こった時には、移行の作業等に起因してもっと状況がややこしく、原因を突き止めるのに苦労したのですが、その移行作業の問題点というのは本題を外れるので、いずれ機会があれば書きたいと思います。データベースの話と言いながらマネジメントの話っぽくなってしまいましたね。


論理削除か物理削除か

久しぶりにITの話をしたいと思います。情報システムには多くの場合リレーショナルデータベース(RDB)を利用しています。たとえスマートフォンのアプリであっても内部で組込み用のRDBを使っていることがあります。

RDBではテーブルという単位でデータの鋳型を定義して、その鋳型で出来る実際のデータはレコードと呼んでいます。レコードが不要になった時、レコードを削除するとその情報は消えてしまいます。一方で「削除したよ」という情報を付与するだけでレコード自体を残すことがあります。この場合、俗に前者を物理削除、後者を論理削除と呼んでいます。実はこの両者が、DB設計において一つのテーマであります。

それぞれのメリットとデメリット

というのも、物理削除の場合、一旦消してしまうとバックアップデータから復元するしかありません。もしバックアップデータが無ければ復元する方法はなく、必要ならもう一度登録し直さなければなりません。

また、論理削除の場合、うっかり削除してしまっても簡単に復元することができますが、本当に不要になっても完全に削除することが出来ず、ゴミ(不要なデータのことを俗にこう呼びます)が残ります。その場合、別に物理削除を行う手段を設ける必要があります。

操作画面上で「削除」というボタンが有った場合に、物理削除の場合は確認ダイアログを表示して本当に削除して良いかしつこいくらいに尋ねる必要があります。しかし論理削除の場合は確認なしに削除してしまっても簡単に復元できるので、結果として操作画面の利便性は向上することになります。

つまり、たかがDB設計なのですが、論理削除か物理削除かというのは運用設計や画面設計とも密接に絡んでくる複雑な話なのです。

私はRDBを学び始めて間もない頃、あるいくつかの現場では全てのテーブルに削除フラグを設けているRDBを見たことがあります。その影響もあって私は全てのテーブルに削除フラグを設ける方針で他の現場でもDBを設計していました。事実、内部統制が緩い現場においてうっかりの操作ミスが多く、論理削除を採用していたことによって何度も助けられたことがあります。しかし一方で次のような課題もお客様から突き付けられました。

  • 間違えて登録したデータを完全に削除できないのは困る。
  • あるデータに関しては通常の運用で完全に削除したい。

論理削除か物理削除かを決めるもう一つの観点は、取り扱うデータが情報資産であるかどうかです。情報資産というのはデータの所有者が、それを保有することに価値を見出している情報という意味です。一定の役目を終えたからと言って完全に削除してしまうと、新たなデータの参考にすることすらできなくなります。その場合は論理削除が良いのではないかと思っています。

削除フラグと設計方針

そもそも「論理削除」の業務的(仕様的)な意味は何でしょうか。もし本当に論理的に削除したということ以上の意味が無ければそれでも良いかもしれませんが、本当にそうでしょうか。良く考えてみると実際には「一時的に非表示にした」「公開を終了した」「有効期限を過ぎた」「処理が終了した」「退会した」といった意味があるのではないでしょうか。そうすると、論理削除を表すには「削除フラグ」よりも「公開フラグ」や「表示フラグ」「処理済みフラグ」という呼称の項目を設けた方が良さそうですね。あるいはそれらを複合的に取り扱う「ステータス」という項目を設けてもいいかもしれません。

また別のアプローチとして有効期間の開始日時と終了日時、公開期間の開始日時と終了日時を管理するという方法もあります。この場合、クエリー(問合せ)は多少煩雑にはなりますが、緻密な管理が実現できます。

ステータス管理が必要なデータは適切な管理項目を設けてステータスを変更し、単純な間違いなどのゴミデータは物理削除できるようにする。そして、ステータス管理の必要のないデータはそのまま物理削除するというのが現実的な方針かなと思っています。いずれにせよ、条件反射のようになんでもかんでも削除フラグというのではなく、きちんとデータの特性を考えて設計する必要がありますね。