IBMのRDBMS『DB2』のデータを、オープンソースRDBMS『PostgreSQL』に移行したときの作業メモです。
wget http://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-centos96-9.6-3.noarch.rpm rpm -ivh pgdg-centos96-9.6-3.noarch.rpm yum install postgresql96-server
移行先環境では、下記の項目が完了している必要があります。
移行先の環境で、既にDB2サーバへの接続設定済み、または設定が不要の場合は、この部分は読み飛ばしてください。
Qiitでhitさんが公開されている『db2クライアントからdb2サーバに接続する方法』を参考に、DB2クライアントからDB2サーバに接続できるように設定します。
/opt/ibm/db2/V10.5_01/bin/db2 CATALOG TCPIP NODE RMTNODE REMOTE 192.168.1.160リモートサーバのアドレス SERVER リモートサーバのポート番号 OSTYPE リモートサーバのOS種別
/opt/ibm/db2/V10.5_01/bin/db2 CATALOG DATABASE リモートサーバのデータベース名 AS クライアントで参照する際の別名 AT NODE カタログしたリモートノード名 AUTHENTICATION 認証種別
私の環境では下記のように実行しました。
/opt/ibm/db2/V10.5_01/bin/db2 CATALOG TCPIP NODE ノード名 REMOTE 192.168.1.160 SERVER 50000 OSTYPE WIN /opt/ibm/db2/V10.5_01/bin/db2 CATALOG DATABASE DB2NODB AS RMTDB AT NODE RMTNODE AUTHENTICATION SERVER
Dalibo社がGitHub上で公開している『db2topg』をダウンロードし、移行先環境の適当な場所に展開します。
公開されているソースを実行するとdb2topg.plに2点ほど問題が見つかったので、あらかじめ修正します。
文字コードの推測に失敗すると発生するようです。
使用しない文字コードを対象としないよう、db2topg.plの383行目付近の条件を修正します。
my $decoder = guess_encoding($data_guess, qw/iso8859-15 utf8 utf16-le utf16-be/);
my $decoder = guess_encoding($data_guess, qw/utf8 utf16-le utf16-be/);
「DB2ADMIN」などは環境によって変化すると思います。
DB2のコメント形式が出現すると発生するようです。
コメント出現時に無視するよう、db2topg.plの1081行目付近に条件を追加します。
elsif ($line =~ /^\/\*\*\*\*\*\*/) { next; }
db2topgに含まれる.plファイルに対して実行権限を付与しています。
実行権限を付与しない場合、以下の手順では適宜お使いの環境に合わせて読み替えてください。
DB2から移行対象となるデータベースのDDLなどを出力します。
私の場合、-zオプションを付けて対象スキーマを絞ってしまいましたが、省略するとデータベースをまるごと移行できるようです。
/opt/ibm/db2/V10.5_01/bin/db2look -d DB2のデータベース名 -z DB2の対象スキーマ名 -i DB2のユーザ名 -w DB2のログインパスワード -e -l -xd -o DB2からの出力スクリプトファイル名.sql
/opt/ibm/db2/V10.5_01/bin/db2look -d rmtdb -z db2admin -i db2admin -w db2admin -e -l -xd -o my_db2_sql_script.sql
./db2topg.pl -f my_db2_sql_script.sql -o DB2データの出力ディレクトリ -d DB2のデータベース名 -u DB2のユーザ名 -p DB2のログインパスワード
./db2topg.pl -f my_db2_sql_script.sql -o db2pg_migration -d rmtdb -u db2admin -p db2admin
cd DB2データの出力ディレクトリ
cd db2pg_migration
使用している環境によって変化してくると予想しています。
私の環境では「 OCTETS」と 「DEFAULT “SYSIBM”.”DATE(‘9999-12-31’)」がさしあたって不要だったので、sedコマンドで除去しました。
sed -e 's/ OCTETS//g' -e 's/ DEFAULT "SYSIBM"."DATE"('\''9999-12-31'\'')//g' before.sql > _before.sql
psql -e –set=ON_ERROR_STOP=1 –single-transaction -f _before.sql PostgreSQLのデータベース名
psql -e --set=ON_ERROR_STOP=1 --single-transaction -f _before.sql pgdb_migration
before.sqlを実行するとロールが作成されます。
このため、2回目以降の実行エラーが発生し以後の処理が行われません。
回避するため、before.sqlの実行前に作成されたロールの削除が必要になるケースがあります。
psql -e –set=ON_ERROR_STOP=1 –single-transaction -c ‘drop role PostgreSQLのロール名’ -U PostgreSQLのログインユーザ名 -d postgres
psql -e --set=ON_ERROR_STOP=1 --single-transaction -c 'drop role db2admin' -U postgres -d postgres
/opt/ibm/db2/V10.5_01/bin/db2 -f export.db2
../deltocopy.pl -d . | psql -e –set=ON_ERROR_STOP=1 PostgreSQLのデータベース名
../deltocopy.pl -d . | psql -e --set=ON_ERROR_STOP=1 pgdb_migration
psql -e –set=ON_ERROR_STOP=1 –single-transaction -f after.sql PostgreSQLのデータベース名
psql -e --set=ON_ERROR_STOP=1 --single-transaction -f after.sql pgdb_migration
psql -e -f unsure.sql PostgreSQLのデータベース名
psql -e -f unsure.sql pgdb_migration
このステップでは、ビューに対するコメントづけが失敗するケースがあるようです。
ビューそのものの移行は行われるので、特に必要が無ければ無視しても大丈夫だと思います。
ユーザ名やパスワードの設定などが相当ゆるゆるの環境で手順の検証を行いましたが、上記の手順でDB2のデータがPostgreSQLに移行できました。
文字化け等も発生していないように見受けられますが、現在確認を進めている最中です。
PostgreSQLに移行したデータは、publicスキーマではなくDB2で使用していたスキーマ名を引き継いで移行されることに注意が必要です。
検証はしていませんが、DB2サーバにアクセスできPerlが動く環境があれば、Linux環境以外でも実行できそうな感じがします。
# # DB2サーバが別のサーバで実行されていて、DB2クライアントからDB2サーバに接続する場合に実行 # RMTNODE ノード名 # 192.168.1.xxx リモートサーバのアドレス # 50000 リモートサーバのポート番号 # WIN リモートサーバのOS種別 # /opt/ibm/db2/V10.5_01/bin/db2 CATALOG TCPIP NODE RMTNODE REMOTE 192.168.1.xxx SERVER 50000 OSTYPE WIN # # ---- # DB2NODB リモートサーバのデータベース名 # RMTDB クライアントで参照する際の別名 # RMTNODE カタログしたリモートノード名 # SERVER 認証種別 # /opt/ibm/db2/V10.5_01/bin/db2 CATALOG DATABASE DB2NODB AS RMTDB AT NODE RMTNODE AUTHENTICATION SERVER ############################################################################################# # ---- # DB2からDDLなどを出力 # ---- # /opt/ibm/db2/V10.5_01/bin/db2look -d DB2のデータベース名 -z DB2の対象スキーマ名 -i DB2のユーザ名 -w DB2のログインパスワード -e -l -xd -o DB2からの出力スクリプトファイル名.sql /opt/ibm/db2/V10.5_01/bin/db2look -d RMTDB -z db2admin -i db2admin -w db2admin -e -l -xd -o my_db2_sql_script # ---- # 念のためUTF8変換 # ---- # nkf --utf8 DB2からの出力スクリプトファイル名.sql > db2.utf8.sql nkf --utf8 my_db2_sql_script.sql > db2.utf8.sql # ---- # PostgreSQL変換用のスクリプトを出力 # ---- # ./db2topg.pl -f db2.utf8.sql -o DB2データの出力ディレクトリ -d DB2のデータベース名 -u DB2のユーザ名 -p DB2のログインパスワード ./db2topg.pl -f db2.utf8.sql -o db2pg_migration -d RMTDB -u db2admin -p db2admin # ---- # PostgreSQL変換用のスクリプトを出力 # ---- # cd DB2データの出力ディレクトリ cd db2pg_migration # ---- # 2回目以降の実行の場合、すでに既存ロールdb2adminが存在しているので、これを削除 # ---- # psql -e --set=ON_ERROR_STOP=1 --single-transaction -c 'drop role PostgreSQLのロール名' -U PostgreSQLのログインユーザ名 -d postgres psql -e --set=ON_ERROR_STOP=1 --single-transaction -c 'drop role db2admin' -U postgres -d postgres # ---- # before.sqlにはDB2固有の表記が含まれているので実行前に" OCTETS"や"SYSIBM"で始まるデフォルト値設定を取り除く # ---- sed -e 's/ OCTETS//g' -e 's/ DEFAULT "SYSIBM"."DATE"('\''9999-12-31'\'')//g' before.sql > _before.sql # ---- # 変換用スクリプト実行(before - テーブルなどの作成) # ---- # psql -e --set=ON_ERROR_STOP=1 --single-transaction -f _before.sql PostgreSQLのデータベース名 psql -e --set=ON_ERROR_STOP=1 --single-transaction -f _before.sql pgdb_migration # ---- # DB2からデータをエクスポート # ---- /opt/ibm/db2/V10.5_01/bin/db2 -f export.db2 # ---- # DB2のデータをPostgreSQLにインサート # ---- # ../deltocopy.pl -d . | psql -e --set=ON_ERROR_STOP=1 PostgreSQLのデータベース名 ../deltocopy.pl -d . | psql -e --set=ON_ERROR_STOP=1 pgdb_migration # ---- # 変換用スクリプト実行(after) # ---- # psql -e --set=ON_ERROR_STOP=1 --single-transaction -f after.sql PostgreSQLのデータベース名 psql -e --set=ON_ERROR_STOP=1 --single-transaction -f after.sql pgdb_migration # ---- # 変換用スクリプト実行(unsure) # Viewのコメント付けが失敗する # ---- # psql -e -f unsure.sql PostgreSQLのデータベース名 psql -e -f unsure.sql pgdb_migration
Please give us your valuable comment