トップ «前の日記(2019-04-27) 最新 次の日記(2019-04-29)» 編集

2019-04-28 [長年日記]

_ RDBMSと変更履歴のメモ

問題意識

いわゆるマスタ系(リソースエンティティ)の履歴をどこまで考える必要があるのかなーということをぼんやり考えるために一度ざっくり整理してみよう。くらい。

最近は Event Sourcing とか単純な CRUD でないデータを扱うものに関心が強い*1ので、なんかこの辺からやり直しが要るんじゃね、てなことを考えている。

まとめ

  • 単純に履歴が追えればよいだけなら paper_trail gem でよい
  • 過去データにも JOIN したいとなると変更履歴を全部持つ table が必要
    • begin と end を指定できるカラムを追加するのがよくあるパターン
    • 単に update を create として別テーブルに記録するパターンを考えてみたけど「事前」にデータを用意できない
    • いずれにせよ監査目的(誰がどんな変更したか)のログと実際のデータの変更ログが混ざる
  • 監査ログと変更ログを分離して扱うにはバイテンポラルデータモデルですよ

参考

「グラス片手に」は割と評判がよいと思っていたんだけど、業務として気にしなければいけない大切なことは書かれているけど、コラムで触れている内容こそ気になっていた人間からするとやや物足りない感じになっている*2。あと理論系の参考書籍なんかも挙げてもらえると嬉しかったんだけど、その辺は自分で頑張って補完する必要がありそう。

バイテンポラリという言葉がどうにも最初うまく頭に入ってこなかったんだけど、自分で考えてみてもう一度読み直したらよく分かってきた。

paper_trail gem

https://github.com/paper-trail-gem/paper_trail

paper_trail はまるごと versions table に放り込む方式。リソース(マスタ)はデータ量がそこまで大きくないという前提に立つと、うっかりリソースと密になるとそのものが削除になった時に困るので、全部まとめて versions 方式も理に叶ってる気がする。

ただ、これだけだと単純に CRUD の履歴が追える程度になりそう。

CMS的なものの編集履歴が見れる、監査ログが採れる、程度ならこれだけでもよいのかもしれない。

currentの情報を重視して過去に対してJOIN可能なだけのtableを素朴に作ってみる

本当に過去だけを考えてみる。例えば「受注」のように

  • その時点の商品
  • その時点の定価
  • その時点の販売担当者、販売部門
  • その時点の税金

などを記録し、過去のバージョンに対しても JOIN して集計を求めることができるようにすることを考える場合、

  • ほぼ同じ構造の table を二つ用意

する方法がありそう。*3役割は

  • resource current ( read only )
  • resource history ( create only )
    • こっちにはいつから有効になったかの日付情報が入る

データを作成する時の選択肢としては current を参照するが、実際に記録する際には同じ code の最新の id を持つものに JOIN する。

ただしこの方法では

  • 監査のためのログ
  • 「商品」の変更ログ

の両方が混ざる。

というのを考えてみたけど、これは後述のスナップショットデータモデルでもトランザクション時間データモデルでもない別なナニカのようだ。

データモデルを整理した資料より

まさに2種類の時間と4種類の要件という話が述べられている。扱っているデータモデルは以下の4種類。(なんだけど、自分が素朴に考えてみたやつはどれでもなかった。)

  • スナップショットデータモデル
    • いわゆる論理削除とか
  • トランザクション時間データモデル
    • 最新のデータも、任意の時点のデータも取得しやすい
  • 有効時間データモデル
    • トランザクション時間 - 変更履歴
    • 事実として残したいデータだけが残る
    • update が許可されているので監査したい場合は別にログを残す必要がある
    • そこだけ paper_trail にする方法はアリかも
  • バイテンポラルデータモデル
    • システム上の時間とデータとしての時間の両方を記録する
    • 監査対応と事実としてのデータの両方を区別できるようにするため

ただちょっと思ったのは、データモデリング的にはバイテンポラルデータモデルが素直で正しいのかもしれないけど、レコードレベルで権限管理できないと、例えばすでに退社済みの人のデータに誰でもアクセスできてしまう、といったことが起きる。データモデリングではなく業務の設計としてどうなのかという問題が残るような気がする。この場合、スナップショットモデルとトランザクション時間データモデルの中間のような自分の考えたアイディアは有効に機能しそうな気がしなくもない。

activerecorde-bitemporal

kufu/activerecord-bitemporal: BiTemporal Data Model for ActiveRecord

誰かと思ったら SmartHR さんですよ。これは SmartHR さん分かってらっしゃる感じがしますねぇ。

関係ないけど

読む時は Kindle 端末やスマホの Kindle アプリで読んでおいて、こうして書き留める際に PC の Kindle アプリで引っ張ってくる、ってのはなかなかいいんだけど、これは Kindle 本でしか実現できなくて、ドキュメントに対しては同じソリューションがないんだよなー、つらい。

Tags: DBMS

*1 Event Sourcingの話はどこかにメモを起こすかもしれないし起こさないかもしれない

*2 履歴ログが残る構造とか暗号化の話とか

*3 あとで気づいたけど二つに分ける必要はない。view でもなんでもよい。