DB2のデータベースをPostgreSQLに移行する方法

月曜日 , 12, 6月 2017 Leave a comment

IBMのRDBMS『DB2』のデータを、オープンソースRDBMS『PostgreSQL』に移行したときの作業メモです。

作業環境

移行元の環境
  • Windows 10 Pro(64ビット版)
  • DB2 Express-C v10.5
移行先の環境
  • CentOS 6.9(64ビット版)
  • PostgreSQL 9.6.3
  • DB2クライアント v10.5
PostgreSQLはpostgresql.orgよりyumコマンドでインストールしています。

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

事前準備

移行先環境では、下記の項目が完了している必要があります。

  • Perlが使える状態になっている。
  • Perl ::CSV::XSが使える状態になっている。
  • DB2クライアントが使える状態になっている。
  • PostgreSQLのユーザ(データベースの作成権限、ロールの作成権限付き)が登録されている。
  • PostgreSQLの移行先データベースが作成されている。

DB2クライアントからDB2サーバに接続できるようにする

移行先の環境で、既に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

DB2移行ツールの導入

Dalibo社がGitHub上で公開している『db2topg』をダウンロードし、移行先環境の適当な場所に展開します。

公開されているソースを実行するとdb2topg.plに2点ほど問題が見つかったので、あらかじめ修正します。

  1. 「iso-8859-15 or utf8 at ./db2topg.pl line 383.」と出力される。

文字コードの推測に失敗すると発生するようです。
使用しない文字コードを対象としないよう、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/);
    
  1. I don’t understand </****** ※ 「DB2ADMIN」は適切なスキーマ名を設定してください。>

「DB2ADMIN」などは環境によって変化すると思います。
DB2のコメント形式が出現すると発生するようです。
コメント出現時に無視するよう、db2topg.plの1081行目付近に条件を追加します。

  • 修正後
    elsif ($line =~ /^\/\*\*\*\*\*\*/)
    {
        next;
    }

    db2topgに含まれる.plファイルに対して実行権限を付与しています。
    実行権限を付与しない場合、以下の手順では適宜お使いの環境に合わせて読み替えてください。

DB2からDDLなどを出力

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

PostgreSQL変換用のスクリプトを出力

./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

DB2固有の表現の変更または削除

使用している環境によって変化してくると予想しています。
私の環境では「 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

変換用スクリプト実行(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

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

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)

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

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください