SchemaSyncCheck

Alto DBFlute のパートです。

SchemaSyncCheckとは?

二つのスキーマ構造に違いがないかどうか? をチェックする機能です(@since 0.9.8.4)

結合DBと開発DBの比較

例えば、結合DBと開発DBで本当に同じスキーマ構造をしているのかどうか不明なときに、確認作業の支援機能として利用できます。 本来はそのような状況が発生しないような仕組み作りが必要ですが(例えば、ReplaceSchema を活用するなど)、 どうしてもズレが発生する可能性のある仕組みが既にでき上がってしまっている場合に SchemaSyncCheck を使ってチェックすると良いでしょう。

本番DBと開発DBの比較

また、本番運用をしているうちに、どうしても本番DBと開発DBがズレていってしまうこともあるでしょう。もしくは、ズレてるのかどうかがわからなくて不安だったり...。 こちらも同じく AlterCheck などを使ってズレが発生させないようなそもそもの仕組み作りが大切ですが、それができない場合や、その仕組みを導入する以前に既にズレがある場合に SchemaSyncCheck を使ってチェックすると良いでしょう。

本番DBは運用していますので直接接続はできませんし、接続すべきではないでしょう。この場合は、本番DBのスキーマ構造だけを DBMS の機能を使ってダンプしてテスト環境に復元して SchemaSyncCheck を使うと良いでしょう。

利用方法

この機能は、オプションです。まずは、documentDefinitionMap.dfprop の schemaSyncCheckMap で同期チェック対象スキーマの情報を設定します。

e.g. schemaSyncCheckMapの仕様 @documentDefinitionMap.dfprop
; schemaSyncCheckMap = map:{
    ; url = [connection url] # デフォルト: databaseInfoMap.dfpropのものと同じ
    ; catalog = [catalog (database name)] # デフォルト: url から自動判別される
    ; schema = [schema] # デフォルト: 設定なし (スキーマの概念のないDBMSでは空指定)
    ; user = [user] # 必須
    ; password = [password] # デフォルト: 設定なし
}

そして、Manageタスクで schema-sync-check を実行すると(@since 0.9.9.7B)、チェック処理が行われるようになります。

e.g. Manageタスクで SchemaSyncCheck の実行 (シェル) @Command
...$ sh manage.sh schema-sync-check

 or

...$ sh manage.sh   // Enter, and then select the number

もし、同期されていない(構造に違いがある)場合はManageタスクがエラーで中断し、[DBFluteクライアント]/output/doc 配下に sync-check-result.html (@since 0.9.9.7F) という形式の名前で差分が出力されます。

0.9.9.7B より前ではDocタスクにて

0.9.9.7B より前のバージョンでは、Manageタスクでの実行ではなく、 プロパティの設定を有効にしてDocタスクを実行すると SchemaSyncCheck が実行されました。

スキーマ差分の確認

previous が同期チェック対象スキーマで、schemaSyncCheckMap にて定義されているものとなります。 next は、databaseInfoMap.dfprop で定義したメインとして接続しているスキーマです。

previous
schemaSyncCheckMapで定義したスキーマ
next
databaseInfoMap.dfpropで定義したスキーマ ※こちらが正しいと想定

例えば、"Add Table" は、schemaSyncCheckMapで定義したスキーマに "そのテーブルを追加すべし" という意味になります。(databaseInfoMap.dfpropの方が正しいのであれば)

同期チェックの仕様は、HistoryHTMLでの差分抽出ロジックと(制限も含めて)同じです。

本番DBの継続的チェック

あらかじめやりやすいように環境を

DBを長く運用していくのであれば、継続してチェックしていく土台を作っておくと良いでしょう。

  1. 本番DBのDDLをダンプ (データなし、構造だけ) ※ほとんどのDBMSでこの機能があるはず
  2. ローカルにて、そのDDLを流して本番DBと同じ構造を持つスキーマを作る ※開発用スキーマとは別に
  3. 開発用スキーマと、そのスキーマを SchemaSyncCheck!

この流れを、あらかじめやりやすいように環境を作っておきましょう。

もし、ReplaceSchemaで実行できるDDLなら

本番DBでのDDLダンプとローカルでの復元はDBMSによってやり方が変わるので、楽にできるのであれば特に問題はありませんが、 そのDDLが ReplaceSchema で素直に実行できるものであれば、同期チェック用のスキーマ (syncdb) を作成する ReplaceSchema を用意しておくとよいでしょう。

  1. playsql配下に syncdb ディレクトリを作って、そこに本番DBを復元できるDDLを配置
  2. dfprop配下に syncdb ディレクトリを作って、そこに syncdb 用のdfpropを配置
  3. DBFluteクライアント配下に syncdb 用の ReplaceSchema のスクリプトを作る
e.g. 同期チェック用のスキーマ syncdb を構築するための環境作り @Directory
dbflute_exampledb // DBFluteクライアント (ここでは exampledb スキーマ)
 |-dfprop
 |  |-syncdb // syncdbスキーマ用のdfprop (+を付けて差分オーバーライドがオススメ)
 |  |  |-databaseInfoMap+.dfprop
 |  |  |-replaceSchemaDefinitionMap+.dfprop
 |  |
 |  |-databaseInfoMap.dfprop // こっちはもともとある開発スキーマ用のdfprop
 |  |-replaceSchemaDefinitionMap.dfprop
 |  |-...
 |-...
 |-playsql
 |  |-data
 |  |  |-...
 |  |
 |  |-syncdb // syncdbスキーマ用のReplaceSchemaのディレクトリ
 |  |  |-replace-schema-00-system.sql
 |  |  |-replace-schema-99-syncdb.sql // 本番DBを復元できるDDL
 |  |
 |  |-replace-schema-00-system.sql
 |  |-replace-schema-10-basic.sql // こっちはもともとある開発スキーマ用のDDL
 |
 |-_project.bat
 |-_project.sh
 |-...
 |-syncdb-replace-schema.bat
 |-syncdb-replace-schema.sh

databaseInfoMap+.dfprop と replaceSchemaDefinitionMap+.dfprop は、差分オーバーライドで syncdb 用に内容を変更します。

databaseInfoMap+.dfprop には、syncdb用のDB接続情報を設定します。もし、そのDDLを実行するのにシステム権限が必要ならば、システムユーザ(rootなど)を設定しましょう

e.g. ExampleDBの同期チェック用のスキーマ examplesyncdb への接続 (MySQL) @databaseInfoMap+.dfprop
map:{
    ; url = jdbc:mysql://localhost:3306/examplesyncdb?characterEncoding=UTF-8
    ; user = examplesyncdb
    ; password = examplesyncdb
}

replaceSchemaDefinitionMap+.dfprop には、ReplaceSchemaで playsql/syncdb ディレクトリが利用されるような設定をします。

e.g. ReplaceSchemaのディレクトリを syncdb に @replaceSchemaDefinitionMap+.dfprop
map:{
    ; playSqlDirectory = playsql/syncdb
}

syncdb用のスクリプトでは、dfprop/syncdb 配下の dfprop がタスク実行時に利用されるようにするために、環境変数 DBFLUTE_ENVIRONMENT_TYPE を syncdb に設定します。

e.g. DBFLUTE_ENVIRONMENT_TYPE に syncdb を設定 (bat) @syncdb-replace-schema.bat
@echo off

setlocal
%~d0
cd %~p0
call _project.bat

set DBFLUTE_ENVIRONMENT_TYPE=syncdb

echo /nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
echo ...Calling the ReplaceSchema task
echo nnnnnnnnnn/
...
e.g. DBFLUTE_ENVIRONMENT_TYPE に syncdb を設定 (shell) @syncdb-replace-schema.sh
#!/bin/bash

cd `dirname $0`
. _project.sh

export DBFLUTE_ENVIRONMENT_TYPE=syncdb

echo "/nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
echo "...Calling the ReplaceSchema task"
echo "nnnnnnnnnn/"
...

replace-schema-99-syncdb.sql には、ダンプしたDDLの内容をそのまま転記します。

この状態で、syncdb-replace-schema.bat(sh)を叩くと、syncdbスキーマ (例だと examplesyncdb) が本番DBと同じ構成で作成されます。まあ本番に限らず、とにかく replace-schema-99-syncdb.sql に DDL を転記して叩けば、そのDDLが syncdb スキーマに反映されるという感じです。

もし、ReplaceSchema管理しづらい形式のものであれば、DBMSのやり方に沿って手動復元します。 その方が簡単な場合もあるので、無理にReplaceSchema管理にする必要もありません。

syncdbと比較するSchemaSyncCheck設定

documentDefinitionMap+.dfprop (これは dfprop ディレクトリ直下の dfprop です) にて、開発用スキーマとsyncdbスキーマと比較する SchemaSyncCheck の設定をします。

e.g. syncdbと比較するSchemaSyncCheck設定 @documentDefinitionMap.dfprop
; schemaSyncCheckMap = map:{
    ; url = jdbc:mysql://localhost:3306/examplesyncdb?characterEncoding=UTF-8
    ; schema =
    ; user = examplesyncdb
    ; password = examplesyncdb
    ; isSuppressCraftDiff = true
}

この設定は、他の挙動に影響を与えるものではありませんので、固定的に設定しておいてもOKです。

ここでは本番のDDLだけをダンプすることを前提としているので、CraftDiffが有効になっているとデータの差分が出てしまいます。 isSuppressCraftDiff (@since 1.0.5G) を設定して CraftDiff を抑制するようにしています。 サポートされていないバージョンの場合は、CraftDiffによるチェック以外の差分がないことを目視すればOKです。 (CraftDiffも比較もしたいのであれば、対象のデータだけを抽出するような形にしなければなりません)

ということで、定期的にチェックするための土台が整いました。そろそろチェックしてみたいと思ったら、syncdbを作成してManageタスクを叩いて SchemaSyncCheck を実行してみましょう。