Azure Data Factory の PostgreSQL コネクタで発生する「Could not load type ‘NpgsqlTypes.NpgsqlInterval’」エラーの原因と解決策(自己ホスト統合ランタイム/SHIR 由来の不整合に注意)
本記事では、Azure Data Factory(ADF)の PostgreSQL コネクタでデータ抽出時に突如として発生しうる下記エラー:
Could not load type 'NpgsqlTypes.NpgsqlInterval' from assembly 'Npgsql, Version=4.0.9.2'
について、技術的背景、迅速な復旧手順、恒久対策までを一気通貫で解説します。とくに、数か月安定稼働していたのに「最近 ADF やパイプラインを触っていないのに突然落ち始めた」という状況に心当たりがある場合、自己ホスト統合ランタイム(Self-hosted Integration Runtime/SHIR)の自動更新を起点とした ドライバの不整合が濃厚です。運用を止めない応急回避(SQL キャスト)から、確実な復旧(SHIR の再起動/ロールバック/修正版への更新)まで、すぐに着手できる具体策をまとめました。
現象の要点
- ADF の新しい PostgreSQL コネクタで数か月運用後、特定のテーブルのみまたは全テーブルで上記エラーが突発。
- 最近、ADF 側の変更は一切なし。それでも突然失敗する。
- エラーの多くは
interval/time/timestampを含む列で顕在化。 - どこを直すべきか(ADF 側か PostgreSQL 側か)判断しづらい。
結論:多くの環境で、SHIR の自動更新をきっかけに、コネクタが読み込む Npgsql ライブラリと ADF 側の型解決がズレ、NpgsqlTypes.NpgsqlInterval が見つからずに例外化する、という構図が見られます。
最短で復旧したい人向けの TL;DR
- SHIR を再起動(サービス再起動または OS 再起動)。これだけで解消する事例あり。
- 解消しない場合は、SHIR を修正版に更新(または安定稼働していた 既知の旧版 5.45.x へダウングレード)。更新後は再起動。
- 運用を止められない場合の暫定回避:問題の列を
::textへキャストして抽出(コネクタ側の型バインディングを迂回)。 - ソースが Azure 上の DB なら、コネクタを「Azure Database for PostgreSQL」コネクタへ切り替えると改善する事例あり。
技術的背景:なぜ「NpgsqlInterval を読み込めない」のか
ADF の Copy Activity / Data Flow は、SHIR 上で各種 DB ドライバ(ここでは Npgsql)を読み込み、型ごとのリーダー・ライターを組み合わせてデータを搬送します。ところが、SHIR の自動更新によって、
- コネクタ側が期待する
Npgsqlの型とシグネチャ(NpgsqlTypes.NpgsqlInterval等) - 実際にロードされた
Npgsqlアセンブリの中身(型の有無や名前空間、実装差)
に矛盾が発生すると、下記のような例外がスローされます。
System.TypeLoadException: Could not load type 'NpgsqlTypes.NpgsqlInterval'
from assembly 'Npgsql, Version=4.0.9.2, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'.
つまり、コードはその型を使おうとしているが、実体のアセンブリには登録がない、という状態です。とくに interval を含む行の読み出し・マッピング時に、この乖離が顕在化しやすいのが実運用でのパターンです。
まず試すべき対応(優先度順)
| 対応策 | 詳細 | 備考 |
|---|---|---|
| SHIR を再起動 | 自動更新後の一時的な読み込み不整合が解け、再起動だけで正常化するケースがある。 | 最も手軽。まずはこれから。 |
| SHIR を安定版へダウングレード | 問題が出たビルド(例:5.48.9106.2)から、過去に正常だった 5.45.x に戻して再起動。 | ダウングレード後は自動更新を一時停止推奨。 |
| 修正版 SHIR へアップデート | 同系統の 5.48 系でも、差し替え済みの修正版インストーラに更新し、再起動。 | 更新後は IR Manager でビルド日付・ファイル更新日時も確認。 |
| 該当データ型を文字列キャスト | interval / time / timestamp 列に限り、クエリ側で ::text キャストして抽出。 | 恒久対応までの一時しのぎ。コピー先スキーマは string に合わせる。 |
| コネクタ種類を切り替える | ソースが Azure 上の PostgreSQL の場合、従来の「PostgreSQL」ではなく「Azure Database for PostgreSQL」コネクタを利用。 | オンプレミスには適用不可。ファイアウォール/接続方式の違いに留意。 |
診断チェックリスト(原因の切り分け)
1. 影響範囲の把握
- 全テーブル/一部テーブルのどちらで失敗するか。
- 一部なら「どの列型で失敗しているか」を確認。傾向として、
interval、time、timestampを含むテーブルで発生しやすい。
2. PostgreSQL 側で型を一覧する SQL(例)
-- interval / time / timestamp を含む列を洗い出す
SELECT
table_schema, table_name, column_name, data_type
FROM information_schema.columns
WHERE data_type IN ('interval', 'time without time zone', 'time with time zone',
'timestamp without time zone', 'timestamp with time zone')
ORDER BY table_schema, table_name, ordinal_position;
3. SHIR のビルド確認
- 対象サーバの「Integration Runtime(IR)構成マネージャ」を開き、バージョンとビルド日時を確認。
- 最近自動更新されていないか、Windows のイベントログ(アプリケーション)や IR ログを参照。
- 高可用(HA)構成の場合、全ノードのバージョンが揃っているかも要確認。
4. 失敗ログの観察ポイント
TypeLoadException: Could not load type 'NpgsqlTypes.NpgsqlInterval'
at Microsoft.DataTransfer.PostgreSql.[...] // 実際はより長いスタックトレース
...
この種の TypeLoadException が出ていれば、ドライバの型解決が主因と考えてよいシグナルになります。
5. コネクタの識別
- Linked service / Dataset で、どのコネクタ(PostgreSQL / Azure Database for PostgreSQL)を使っているかを確認。
- Copy Activity と Data Flow の両方で発生しうるため、両方の設定を点検。
解決策の実装詳細
対応 1:SHIR の再起動
最短で試せる打ち手です。IR Manager からの再起動、またはサービス再起動(高可用構成なら順番に)を行います。PowerShell・コマンドライン派は次のような操作も可能です。
:: サービス名の一例(環境により異なる場合あり)
sc stop "DIAHostService"
sc start "DIAHostService"
- 処理中のパイプラインがある場合は、安全な停止タイミングを見計らうか、別ノードへフェイルオーバーしてから実施。
- OS のメンテナンス再起動も有効。キャッシュや一時ファイルの残骸を含めクリーンに立ち上げ直します。
対応 2:既知の安定版(例:5.45.x)へいったんロールバック
更新で悪化した疑いが濃厚な場合、直近まで安定していたバージョンへ戻すのが確実です。一般的な流れは以下。
- 現行のビルド番号とビルド日時を控える(トラブルシュートの証跡)。
- 対象サーバから SHIR をアンインストール。
- 運用実績のある旧版インストーラ(例:5.45.x)で再インストール。
- IR を ADF に再登録・再接続(キーの貼り付け)。
- サービス起動後、簡単な疎通テスト(軽量の SELECT)で正常性を確認。
- 暫定的に 自動更新を停止し、以後はステージング環境で先行検証→段階展開(リング)を徹底。
ポイント:IR の自動更新を止めると、セキュリティ修正の取り込みが遅れるため、長期放置は非推奨。後述の「恒久対策(リング運用)」で安全に最新版へ戻す前提の一時措置としてください。
対応 3:修正版 SHIR へアップデート
同じ 5.48 系でも、差し替えられた修正版に更新すると解消するケースがあります。インストール後は次を必ず確認します。
- IR Manager のバージョン表示とビルド日付。
- インストール済みファイル(例:
Program Files\Microsoft Integration Runtime\配下)の更新日時。 - 更新後、OS 再起動またはサービス再起動も忘れずに。
対応 4:暫定回避(SQL 側で ::text キャスト)
型バインディングで落ちる箇所を避けるため、問題の列だけ文字列表現に変換して抽出します。Copy Activity の Source にクエリを指定可能です。
SELECT
id,
some_interval_column::text AS some_interval_text,
start_time::text AS start_time_text,
updated_at::text AS updated_at_text
FROM public.sample;
シンク(出力側)のスキーマは string に合わせます。後工程で必要になれば、文字列から interval / time / timestamp へ再解釈する処理を別途用意してください。
| PostgreSQL の元型 | 暫定のキャスト | 備考 |
|---|---|---|
| interval | ::text | 例:'1 day 02:03:04' のような表現に。 |
| time [with/without tz] | ::text | タイムゾーンは文字列で保持。後段でパース。 |
| timestamp [with/without tz] | to_char(col, 'YYYY-MM-DD HH24:MI:SS.US TZ') | フォーマット固定にする場合。単純に ::text でも可。 |
対応 5:コネクタの切り替え(Azure Database for PostgreSQL)
ソースが Azure 上のマネージド PostgreSQL(Single Server, Flexible Server 等)の場合、「PostgreSQL」コネクタではなく「Azure Database for PostgreSQL」コネクタを使うと改善する事例があります。両者は内部実装(利用ドライバや接続経路)が異なり、型の扱いや パラメータ既定も差異があります。
| 項目 | PostgreSQL コネクタ | Azure Database for PostgreSQL コネクタ |
|---|---|---|
| 想定ターゲット | オンプレ/IaaS/任意の PostgreSQL | Azure マネージド PostgreSQL |
| 接続経路 | SHIR 経由(基本) | SHIR / マネージド仮想ネットワーク等 |
| 型互換性 | interval 周辺で不整合の事例あり | 同事例が発生しないケースが多い |
| オンプレ DB 対応 | 可 | 不可 |
よくある質問(FAQ)
Q. パイプラインもクエリも触っていないのに、なぜ突然落ちた?
A. ADF 本体ではなく、SHIR が自動更新されたのがきっかけの可能性が高いです。ドライバ(Npgsql)の型や署名が想定とズレると、アセンブリ読み込み時に TypeLoadException が発生します。
Q. 一部テーブルのみでエラーになるのは?
A. interval / time / timestamp などの時間系の列を含むテーブルで顕在化しやすいからです。その列の読み取りや型マッピング時に型解決が働き、例外につながります。
Q. PostgreSQL のバージョンが古い/新しいことは関係ある?
A. 直接の主因は SHIR 側のドライバとコネクタの不整合です。とはいえ DB のメジャー差分(例:古い 9.x や新しい 15.x など)で型の既定挙動が違うこともあるため、アプリケーション側のマッピングは安定版に揃えるのが無難です。
Q. Data Flow と Copy Activity のどちらで発生?
A. どちらでも起こり得ます。ドライバの型解決は共通レイヤに近いため、両方の経路で再現することがあります。
Q. TimeSpan や string でマッピングすれば直る?
A. ドライバの読み込み・型解決で失敗している場合は、マッピング前にエラーが起きているため、まずは SHIR/ドライバ側の修正や再起動が必要です。緊急回避としては ::text キャストが有効です。
運用に組み込む恒久対策
1. SHIR の「リング」更新と段階展開
- 最小構成のステージング IRを持ち、最新版を先に適用してスモークテスト。
- クリティカルでないパイプラインから順に、本番 IR へ段階展開。
- 想定外のエラーが検知されたら即座にロールバックできるよう、旧版インストーラ・登録情報を保全。
2. 自動更新の制御
- 「常時 ON」ではなく、メンテナンスウィンドウで手動適用に切り替える運用を検討。
- 適用後は必ずOS 再起動/サービス再起動でクリーンにロード。
3. ヘルスチェックとアラート
- 代表的なテーブル(時間型を含む)を対象に、軽量 SELECT の定期実行を設定。
TypeLoadExceptionやNpgsqlのロード失敗を検知する ログ監視を導入。
4. スキーマ設計上のガードレール
- 長期的には、
intervalの活用方針を見直し、必要に応じて正規化された数値表現(秒数やマイクロ秒)やISO 文字列への変換を検討。 - ETL の入口では文字列として受け、DWH 側で目的の型に再キャストする「遅延型付け」戦略も有効。
実践ノウハウ(現場でのハマりどころ)
高可用(HA)構成とノード間のバージョン差
複数ノードの IR を HA 構成にしている場合、一部ノードだけ更新されて障害が出たり、ジョブのフェイルオーバーで症状が出たり消えたりすることがあります。全ノードのバージョンを一致させ、順序立てて更新・再起動を行ってください。
導線を確保する「二重 IR」戦略
ダウンタイム最小化のため、同一ネットワーク内に予備 IR(別ホスト)を用意しておくと安心です。予備 IR に事前に旧版を維持しておけば、障害発生時に Linked service の IR バインドを切り替えるだけで、即時に復旧できます。
クエリの安全な暫定変更
やむなく ::text を導入する際は、限定的なビューを作ってアプリケーションからはそのビューを参照する方法がおすすめです。これなら本体テーブルの参照を変えずに回避策を差し替え可能です。
CREATE OR REPLACE VIEW v_sample_for_adf AS
SELECT
id,
some_interval_column::text AS some_interval_text,
start_time::text AS start_time_text,
updated_at::text AS updated_at_text
FROM public.sample;
復旧後はビュー定義を戻すだけで、パイプライン定義の修正なく運用に復帰できます。
トラブルシュートの深掘り:Npgsql と型マッピング
Npgsql は PostgreSQL の .NET ドライバで、バージョンごとに型マッピングの仕様や実装が変化してきました。interval のように .NET 側で表現が難しい型は、実装の微妙な差が積み重なる領域です。ADF 側のコネクタが 特定の型(NpgsqlTypes.NpgsqlInterval)の存在を前提にしている一方、実際にロードされた Npgsql には当該型が見当たらない──この齟齬が TypeLoadException を引き起こします。
このため、「アプリを触っていないのに壊れた」というときほど、実行基盤(SHIR)側の変更に目を向けるのが効果的です。アセンブリバインディングの差し替えや GAC ではなく、IR が保持する依存バイナリの差で破綻しているケースが支配的です。
ダウンタイム最小の復旧プレイブック
- 影響評価(10~15分):失敗対象(Copy / Data Flow、テーブル、列型)を洗い出す。
- 短期回避(15分):クエリを
::textで暫定化し、急ぎの処理を通す。 - 根本修正(30~60分):SHIR を再起動 → 治らなければ修正版へ更新 or 既知安定版にロールバック。
- 安定化(30分):軽量 SELECT のヘルスチェック、リング更新のラインを整える。
Tip:IR の更新やロールバックは、別ノードで同一 IR(HA)に参加させてからスイッチするのが安全です。これにより、作業中の停止を最小化できます。
チェックリスト(まとめ)
- エラー文字列に
NpgsqlTypes.NpgsqlIntervalが含まれているか? - 該当テーブルに
interval/time/timestampがあるか? - SHIR は最近自動更新されていないか?バージョン・ビルド日時は?
- 再起動で直るか? 直らなければ修正版に更新 or 既知の安定版へロールバック。
- 緊急時は
::textキャストで暫定回避。 - Azure 上の DB ならコネクタ切り替えも検討。
- 以後はステージングで先行検証 → 本番リング展開で更新管理。
サンプル:一時回避と戻しの手順(実践用)
一時回避(ビュー方式)
- 対象スキーマに
_for_adfなどの 暫定ビューを作成。 - 対象列のみ
::textでキャスト。 - ADF 側の Dataset / Source の参照先をビューに切り替え(またはクエリ差し替え)。
復旧後の戻し
- SHIR を修正版に更新 or ロールバック完了後、テスト用パイプラインで正常読取を確認。
- ビューを本来の生テーブルに戻す(または
::textを外したクエリに戻す)。
トラブル再発を防ぐためのテンプレ(運用品質の底上げ)
| 施策 | 内容 | 期待効果 |
|---|---|---|
| リング更新 | Dev → Stg → Prod (A/B) の順で IR を更新。段階的に展開。 | 本番への影響最小化。早期検知。 |
| ヘルスチェック | 時間系列を含む代表テーブルで定時 SELECT を実行し、異常を監視。 | 型不整合の早期発見。 |
| 予備 IR | 同一ネットワークに予備 IR を常設。旧版を保持し即時切替を可能に。 | ダウンタイム短縮。 |
| スキーマ設計ガイド | interval 多用時の表現方針を定め、必要に応じて数値や ISO 文字列で保持。 | ドライバ差異の影響を軽減。 |
まとめ
ADF の PostgreSQL コネクタで発生する Could not load type 'NpgsqlTypes.NpgsqlInterval' は、現場報告を総合すると、SHIR の自動更新を契機とする Npgsql まわりの不整合が本質です。まずは SHIR 再起動 → ダメなら 修正版へ更新 or 過去安定版へロールバック。運用を止められないときは ::text キャストで迂回し、Azure 上の DB であれば Azure Database for PostgreSQL コネクタへの切り替えも有効です。
恒久的には、リング更新・予備 IR・ヘルスチェックの三点セットで「突然壊れた」を仕組みで防ぎましょう。この記事の手順をそのままプレイブックとして取り込み、次回以降は迷わず安全に復旧できる状態を目指してください。
付録:運用メモ(手短版)
- 症状:
NpgsqlTypes.NpgsqlIntervalが見つからない(TypeLoadException)。 - 第一手:SHIR 再起動。
- 第二手:SHIR の修正版へ更新 or 旧版(5.45.x)へ戻す(自動更新は一時停止)。
- 緊急回避:
::textキャストで抽出を継続。 - 代替策:コネクタを「Azure Database for PostgreSQL」に切替(Azure 上の DB 限定)。
- 再発防止:リング更新、予備 IR、時間型を含む疎通テストの定期化。
このガイドが、現場の「今すぐ復旧したい」「二度と同じ事故に遭いたくない」の両方に役立つことを願っています。

コメント