ora2pgが「そもそも動かない」段階で止まる
この記事は要約版です。省略した詳しい解説や手順は、ブログの完全版にまとめています: ora2pg エラーの原因切り分けと対処手順
OracleからPostgreSQLへ移行する作業でora2pgを入れると、スキーマ変換の中身を検討する前に実行そのものが失敗する場面に出会います。install_driver(Oracle) failedで止まる、ORA-12154が返る、SHOW_TABLEを実行しても何も出ない、生成されたDDLが文字化けする。症状はばらばらに見えますが、発生している層は接続、文字コード、変換差異の3つに整理できます。確認する順番を決めておけば短時間で切り分けられます。
接続、文字コード、変換差異の順に見る
ora2pgはPerl製で、DBIからDBD::Oracle、さらにOracleクライアントライブラリのlibclntshを経由してOracleに接続します。取得したメタデータとPL/SQLをPostgreSQL向けに書き換えて出力する構造です。この経路を押さえておくと、エラーがどの層で起きたか見当がつきます。
| 層 | 症状の例 | 主な原因 |
|---|---|---|
| 接続 |
install_driver(Oracle) failed、ORA-12154、ORA-01017、ORA-12541
|
DBD::Oracle未導入、LD_LIBRARY_PATH未設定、DSN書式の誤り、権限不足 |
| 文字コード | 出力SQLが読めない文字になる |
NLS_LANGとDBキャラクタセットの不一致、CLIENT_ENCODING、BINMODE
|
| 変換差異 | 型が意図と違う、PL/pgSQLが構文エラー、値が合わない | 型マッピングの既定値、PL/SQLの非対応構文、Oracle固有のセマンティクス |
この順番を守ってください。接続が怪しいまま型マッピングを調整すると、SHOW_TABLEが空だった理由は権限不足だった、という遠回りになります。
最初に SHOW_VERSION で接続層を確定させる
SHOW_VERSIONは接続してバージョン情報を取るだけの処理です。ここが通ればPerlモジュール、クライアントライブラリ、ネットワーク、認証のすべてをクリアできていると判断できます。
ora2pg -c /etc/ora2pg/ora2pg.conf -t SHOW_VERSION
失敗したらメッセージで分類します。install_driver(Oracle) failedはPerlとクライアントライブラリの構成問題、ORA-12154やORA-12541、ORA-12514はDSNやtnsnames、リスナー側、ORA-01017とORA-28000は認証です。-dを付けるとora2pgが発行しているSQLやディレクティブの解釈結果まで見えます。
ora2pgを疑う前に、同じホストの同じOSユーザーからsqlplusで接続できるかを試しておくと切り分けが速くなります。sqlplusで通ってora2pgで通らないならora2pg.confのDSN書式、どちらも通らないならネットワークや認証側です。
DBD::Oracle が共有ライブラリを解決できているか
install_driver(Oracle) failed系はほぼこの層で決まります。PerlからDBD::Oracleが見えているかを確認してください。
perl -e 'use DBI; print join("\n", DBI->available_drivers), "\n"'
perl -MDBD::Oracle -e 'print "$DBD::Oracle::VERSION\n"'
一覧にOracleが出ない、または2行目がエラーになる場合、DBD::Oracleが未導入か共有ライブラリの解決に失敗しています。Oracle.soをlddにかけてlibclntsh.so.19.1 => not foundと出たら、Instant Clientのパスが実行時に解決されていません。LD_LIBRARY_PATHで都度渡すよりも、ldconfigに登録したほうがcronやsystemd配下でも安定します。
echo /usr/lib/oracle/19.19/client64/lib | sudo tee /etc/ld.so.conf.d/oracle-instantclient.conf
sudo ldconfig
ldconfig -p | grep clntsh
手で叩くと動くのに自動実行で落ちるときは、実行コンテキストに環境変数が渡っていない可能性を先に疑ってください。対話シェルの.bash_profileはcronやCIのジョブには効きません。
SHOW_TABLE が空なら SCHEMA の表記と権限
接続が成功してもSHOW_TABLEが何も返さない場合、まずSCHEMAの値を見ます。Oracleはクォートなしで作成したオブジェクト名を大文字でディクショナリに格納するため、SCHEMA appdataと小文字で書くと一致せず結果が空になります。
次にディクショナリの参照権限です。ora2pgは既定でALL_*やDBA_*ビューを参照します。DBA_*が見えない移行用ユーザーならUSER_GRANTS 1でUSER_*ビューへ切り替えますが、対象は自分が所有するオブジェクトだけになります。他スキーマを吸い出すならSELECT_CATALOG_ROLE相当の権限をDB側で付与してください。all_tablesをオーナー別に集計すれば、どこまで見えているかが確定します。
DSNについては、dbi:Oracle:ORCLのようなTNSエイリアス形式がtnsnames.oraとTNS_ADMINに依存します。ORA-12154が出るならホスト指定形式に切り替えると、原因をtnsnames側から切り離せます。マルチテナント構成ではPDBへ接続するのでservice_name=を使います。
詳しくは
元記事では、install_driver(Oracle) failedの3パターンの原因とDBD::Oracleの再ビルド手順、ora2pg.confの最小構成、文字化け時のキャラクタセット確認SQL、PG_INTEGER_TYPEやMODIFY_TYPEを使った型マッピングの調整、LONGREADLENによるLOBのフェッチエラー対処まで扱っています。自律トランザクションやCONNECT BYのように人手の設計変更が必要なPL/SQLの一覧、ESTIMATE_COSTの見積もりをどこまで使えるか、--init_projectで作った構成を使って移行検証を反復できる状態にする方法もまとめました。