せめてSQL Server 2005とSQL Server 2012であればリプリケーションを使って、片側のデータベースに対する更新を、もう片方のデータベースに反映して同期を取ることも出来るのだけど・・・と、良い方法を探していたところSymmetricDS(http://www.symmetricds.org/)というリプリケーションツールを見つけた。
SymmetricDSはJava SE6以上が動作するOSで、JDBCで接続可能なデータベース間であれば、およそ殆どの異なるアーキテクチャ間のDBを双方向にリプリケーション出来る優れものです。SQL Server 2000でも動作するはずなので、今回の用途にはぴったりです。さっそく試験環境を作成してテストしてみましょう。
1.SymmetricDSのインストール
1.1.SymmetricDSのダウンロード
SymmetricDSのホームページからzipファイルをダウンロードして、インストール先に解凍します。ここではC:\App\symmetricに解凍することにします。
1.2.ルートノードの設定ファイルを作成する
データベースへの接続設定を作成します。データベースへの接続に関する設定はC:\App\symmetric\enginesに保存します。C:\App\symmetric\samplesからcorp-000.propertiesを複製して設定します。今回はrootnode.propertiesという名称にします。
engine.nameには任意の名称を指定します。今回はrootnodeとします。
db.driverにはJDBCドライバの名称を指定します。デフォルトではH2 Databaseが指定されているので、これをコメントにしてnet.sourceforge.jtds.jdbc.Driverのコメントを外します。
db.urlには同期するデータベースへの接続文字列を指定します。デフォルトではH2 Databaseが指定されているので、これをコメントにしてjdbc:jtds:sqlserver://localhost:1433/rootdb;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880;に変更します。rootdbはデータベース名ですが、ここには日本語を指定できません。
db.userにはデータベースへのログインIDを指定します。本来はSymmetricDS用にアカウントを作るべきですが、今回はsaを指定しておきます。
db.passwordには先のログインIDで使用するパスワードを指定します。
sync.urlには同期に使用するHTTP URLを指定します。ここではhttp://localhost:31415/sync/rootnodeと指定します。sync移行に続く文字列はengine.nameで指定した文字列と一致しなくてはなりません。
group.idとexternal.idは、SymmetricDS上でデータベースを一位に識別するためのIDを指定します。ここではgroup.idをrootnode、external.idを000としておきます。
他にもパラメータがありますが、そのままにしておきます。
engine.name=rootnode # The class name for the JDBC Driver ...#db.driver=org.h2.Driver db.driver=net.sourceforge.jtds.jdbc.Driver # The JDBC URL used to connect to the database ... #db.url=jdbc:h2:corp;AUTO_SERVER=TRUE;LOCK_TIMEOUT=60000 db.url=jdbc:jtds:sqlserver://localhost:1433/rootdb;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880; # The user to login as who can create and update tables db.user=sa # The password for the user to login as db.password=xxxxxx registration.url= sync.url=http://localhost:31415/sync/rootdb # Do not change these for running the demo group.id=rootnode external.id=000
1.3.同期対象となるノードの設定ファイルを作成する
データベースへの接続設定を作成します。データベースへの接続に関する設定はC:\App\symmetric\enginesに保存します。C:\App\symmetric\samplesからstore-000.propertiesを複製して設定します。今回はsubnode-000.propertiesという名称にします。
engine.nameには任意の名称を指定します。今回はsubnode-001とします。
db.driverにはJDBCドライバの名称を指定します。ルートノードと同じくデフォルトではH2 Databaseが指定されているので、これをコメントにしてnet.sourceforge.jtds.jdbc.Driverのコメントを外します。
db.urlには同期するデータベースへの接続文字列を指定します。ルートノードと同じくデフォルトではH2 Databaseが指定されているので、これをコメントにしてjdbc:jtds:sqlserver://localhost:1433/subdb01;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880;に変更します。
db.userにはデータベースへのログインIDを指定します。本来はSymmetricDS用にアカウントを作るべきですが、今回はsaを指定しておきます。
db.passwordには先のログインIDで使用するパスワードを指定します。
registration.urlにはルートノードsync.urlの値を指定します。ここではhttp://localhost:31415/sync/rootnodeと指定します。
group.idとexternal.idをルートノードと同様に設定します。ここではgroup.idをsubnode、external.idを001としておきます。
他にもパラメータがありますが、そのままにしておきます。
engine.name=subnode-001 # The class name for the JDBC Driver ...#db.driver=org.h2.Driver db.driver=net.sourceforge.jtds.jdbc.Driver # The JDBC URL used to connect to the database ... #db.url=jdbc:h2:corp;AUTO_SERVER=TRUE;LOCK_TIMEOUT=60000 db.url=jdbc:jtds:sqlserver://localhost:1433/subdb01;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880; # The user to login as who can create and update tables db.user=sa # The password for the user to login as db.password=xxxxxx registration.url=http://localhost:31415/sync/rootdb # Do not change these for running the demo group.id=subnode external.id=001
1.4.ルートノードに制御テーブルを作成する
次のコマンドを実行してルートノードのデータベースに制御テーブルを作成します。これによりデータベースにsym~で始める各種テーブルが作成されます。制御テーブルは別のデータベースに作りたいと思うかもしれませんが、ルートノードで指定したデータベース以外の場所に作ることはできないようです。
bin\symadmin --engine rootnode create-sym-tables
続いてデータベース間の同期方法に関する設定を、上記コマンドで作成されたテーブルにINSERTします。
--既存の設定を削除。sym_channelには既定のテーブルがあるので、作成したものだけ削除するようになっています。 delete from sym_trigger_router; delete from sym_trigger; delete from sym_router; delete from sym_channel where channel_id in ('tblcopy'); delete from sym_node_group_link; delete from sym_node_group; delete from sym_node_host; delete from sym_node_identity; delete from sym_node_security; delete from sym_node; --テーブルのコピーに使用するチャンネルを作成。 --同期でエラーが発生すると、同じチャンネルを使用しているその他の複製処理もエラーが回復するまで待たされます。 --エラーが発生しても並列して複製処理を行いたい場合には、チャンネルを複数作成します。 insert into sym_channel (channel_id, processing_order, max_batch_size, enabled, description) values('tblcopy', 1, 100000, 1, 'Copy Sample Table'); insert into sym_node_group (node_group_id) values ('rootnode'); insert into sym_node_group (node_group_id) values ('subnode'); insert into sym_node_group_link (source_node_group_id, target_node_group_id, data_event_action) values ('rootnode', 'subnode', 'W'); insert into sym_node_group_link (source_node_group_id, target_node_group_id, data_event_action) values ('subnode', 'rootnode', 'P'); --複製の対象テーブルや複製を開始する判断条件を指定します。 --ここではワイルドカードで全てのテーブルを複製するように指定して、それ以外の項目は規定値にしています。 insert into sym_trigger (trigger_id,source_table_name,channel_id,last_update_time,create_time) values('tblcopy','*','tblcopy',current_timestamp,current_timestamp); --複製の方向の指定と、複製するデータのフィルタ条件を指定します。 --複製する条件はdefaultとして全てを複製するように指示しています。 insert into sym_router (router_id,source_node_group_id,target_node_group_id,router_type,create_time,last_update_time) values('root_2_sub', 'rootnode', 'subnode', 'default',current_timestamp, current_timestamp); insert into sym_router (router_id,source_node_group_id,target_node_group_id,router_type,create_time,last_update_time) values('sub_2_root', 'subnode', 'rootnode', 'default',current_timestamp, current_timestamp); --sym_triggerとsym_routerを関連付けています。 insert into sym_trigger_router (trigger_id,router_id,initial_load_order,last_update_time,create_time) values('tblcopy','root_2_sub', 100, current_timestamp, current_timestamp); --ノードの登録を行います。 insert into sym_node (node_id,node_group_id,external_id,sync_enabled,sync_url,schema_version,symmetric_version,database_type,database_version,heartbeat_time,timezone_offset,batch_to_send_count,batch_in_error_count,created_at_node_id) values ('000','rootnode','000',1,null,null,null,null,null,current_timestamp,null,0,0,'000'); insert into sym_node (node_id,node_group_id,external_id,sync_enabled,sync_url,schema_version,symmetric_version,database_type,database_version,heartbeat_time,timezone_offset,batch_to_send_count,batch_in_error_count,created_at_node_id) values ('001','subnode','001',1,null,null,null,null,null,current_timestamp,null,0,0,'000'); insert into sym_node_security (node_id,node_password,registration_enabled,registration_time,initial_load_enabled,initial_load_time,created_at_node_id) values ('000','5d1c92bbacbe2edb9e1ca5dbb0e481',0,current_timestamp,0,current_timestamp,'000'); insert into sym_node_security (node_id,node_password,registration_enabled,registration_time,initial_load_enabled,initial_load_time,created_at_node_id) values ('001','5d1c92bbacbe2edb9e1ca5dbb0e481',1,null,1,null,'000'); --ルートノードのnode_idを指定します。ルートノードは1つだけ作成します。 insert into sym_node_identity values ('000');
1.5.SymmetricDSを起動する
次のコマンドを実行してSymmetricDSを起動します。
bin\sym
正常に起動した場合、sym_~で指定したテーブルや、rootdbにある同期対象のテーブルがsubdb01に複製されデータの同期が開始されます。
2.その他TIPSなど
2.1.日本語への対応
日本語で作成したテーブル名やフィールド名があっても正常に動作しているようです。
ただしデータベース名に日本語を使用する場合はdb.urlで指定することができないので、データベースで使用するユーザーアカウントの既定のデータベースでデータベース名を指定する等の対応が必要になります。
2.2.設定に誤りがあった場合の訂正
設定に誤りがあった場合、テーブルを直接書き換えても認識して動作が変わるのですが、各テーブルに作成された中間データとの整合性が取れなくなる場合があるようで、設定が反映されない場合があります。この場合は”bin/symadmin –engine uninstall”のコマンドを実行して制御テーブルを削除し、あらためて作り直した方がよいです。
2.3.Microsoft製JDBCドライバの使用
Microsoft製JDBCドライバでも問題なく動作しています。
ただしSymmetricDSの開発サイドではjtdsのドライバを使用して動作確認しているとの事なので、そちらを利用したほうがよいでしょう。
「SQL Server 2000とSQL Server 2012のデータ連係(SymmetricDS)」への1件のフィードバック