Azure Database for PostgreSQL Flexible ServerでPostgreSQL 17へのMVU(メジャーバージョンアップグレード)がInternalServerErrorで失敗する場合、原因はデータではなく「ロール付与の履歴」に潜むことがあります。本記事ではazure_pg_adminの挙動変更で起きる失敗パターンと、現場でできる調査・回避策を整理します。
現象:PG17へのMVUがResourceOperationFailure / InternalServerErrorで止まる
Azure Database for PostgreSQL Flexible Server(例:インスタンス名「GIS3D」)で、ポータルの「メジャーバージョンアップグレード(MVU)」からPostgreSQL 17へ上げようとしたところ、アップグレード処理が失敗し、次のようなエラーが表示されることがあります。
- エラーの大枠:ResourceOperationFailure
- 内部エラー:InternalServerError
- 画面やログにTracking ID(相関ID)が付与される
このタイプの失敗は、手元でSQLを直して再実行すればすぐ通る類のエラーに見えにくく、原因切り分けが難しいのが厄介です。特にFlexible Serverはフルスーパーユーザー権限が提供されないため、利用者側で「何が起きたか」を完全に追い切れないケースがあります。
| 観測できる症状 | よくある誤解 | 実際に疑うべきポイント |
|---|---|---|
| MVUが途中で失敗し、InternalServerErrorになる | 「データ量が多すぎる」「ロックが競合した」 | バックエンド処理がロール/権限情報の整合性で止まっている可能性 |
| Tracking IDが表示される | 「こちらで調べようがない」 | Tracking IDはサポート側の調査キー。むしろ最重要情報 |
| SQLのエラーが手元で再現しない | 「原因不明」 | Azure側のシステムロール(azure_pg_admin等)の仕様変更に起因することがある |
結論:azure_pg_adminの挙動変更が一部のロール付与レコードと衝突する
結論から言うと、原因はAzure側のシステムロール azure_pg_admin の挙動変更(改善)が、過去に作られた一部のロール付与(GRANT)パターンと相性が悪く、MVUの内部処理が失敗することにあります。
ポイントは「どのロールが誰のメンバーか」だけでなく、そのロール付与を“誰(grantor)が実行したか”という履歴(メタデータ)までが、PostgreSQLのカタログに残っている点です。MVUは内部でこの情報も扱うため、Azure側のロール解釈が変わると、既存の付与履歴が“矛盾した状態”に見えてアップグレードが止まる、というイメージです。
重要:この事象は「ユーザーの操作ミス」というより、Azure側の仕様変更に起因する既知の地雷として現場で遭遇しやすいタイプです。まずはTracking IDを添えて調査依頼を出せる形に整えるのが堅い進め方になります。
地雷になりやすいGRANTパターン
今回の失敗パターンは、次の条件が揃うと発生しやすい、という整理になります。
| 条件 | 意味 | なぜ問題化しやすいか(実務目線) |
|---|---|---|
admin_user が azure_pg_admin のメンバー | Flexible Serverの管理ユーザーがAzure管理ロールに参加している状態 | azure_pg_adminの権限解釈が変わると、過去の「付与できた/できない」の前提が崩れる |
admin_user が role1 のADMIN(admin option) | admin_userがrole1を他者に付与できる状態 | “誰の権限で付与したか”がカタログに残るため、MVUで整合性チェックに引っかかる余地が出る |
GRANT role1 TO role2 GRANTED BY admin_user など、grantorがadmin_userになる付与が存在 | role1→role2のメンバーシップ付与の記録にadmin_userが刻まれている | Azure側でazure_pg_adminの振る舞いが変わると、このgrantor情報が原因でMVUが失敗することがある |
問題になりやすいSQL例は次のような形です(例示)。
GRANT role1 TO role2 GRANTED BY admin_user;
一方で、回避の方向性としては、grantor(付与者)をadmin_userにしない形に付け替えるのが実務上の落としどころになります。たとえば次のようなイメージです。
-- grantor を role1 側に寄せる(例)
GRANT role1 TO role2 GRANTED BY role1;
-- もしくは、role1 に切り替えて付与する(例)
SET ROLE role1;
GRANT role1 TO role2;
RESET ROLE;
理解のカギ:PostgreSQLは「誰が付与したか(grantor)」も保存する
PostgreSQLのロール付与(= ロールメンバーシップ)は、内部的にはカタログテーブル(システムカタログ)に記録されます。具体的には pg_auth_members に、次のような情報が保存されます。
| 項目 | カタログ上の列 | 意味 | MVUで効いてくる理由 |
|---|---|---|---|
| 付与されたロール | roleid | どのロール(role1)が… | 当然、移行対象として扱われる |
| メンバー(付与先) | member | どのロール/ユーザー(role2)に付与されたか | 権限の実体なので必ずチェックされる |
| 付与者(grantor) | grantor | 誰がその付与を実行したか | Azure側の権限解釈が変わると、整合性の取り方が変わり、ここで詰むことがある |
| ADMINオプション | admin_option | 付与先がさらに他者へ付与できるか | ロール階層が複雑だと、MVU中に権限の「再現」が難しくなる |
普段の運用では「role1がrole2のメンバーかどうか」だけを気にしがちですが、MVUのようなシステム内部で権限を再構築する処理では、grantor情報が足を引っ張ることがあります。今回のケースはまさにそこが刺さっています。
事前調査:admin_userがgrantorになっているロール付与を洗い出す
まずは、問題になり得る付与(grantorがadmin_user)を洗い出します。次のSQLは、pg_auth_members から「付与されたロール」「付与先(メンバー)」「付与者(grantor)」を一覧化する基本形です(管理ユーザー名は環境に合わせて置き換えてください)。
SELECT
r1.rolname AS granted_role,
r2.rolname AS member_role,
r3.rolname AS grantor
FROM pg_auth_members m
JOIN pg_roles r1 ON m.roleid = r1.oid
JOIN pg_roles r2 ON m.member = r2.oid
JOIN pg_roles r3 ON m.grantor = r3.oid
WHERE r3.rolname = 'admin_user';
実務では、これに「ADMINオプションの有無」や「対象ロールの絞り込み」を足すと判断が早くなります。たとえば次のように、admin_option を一緒に出すと、付け替え時の影響範囲を把握しやすくなります。
SELECT
r1.rolname AS granted_role,
r2.rolname AS member_role,
r3.rolname AS grantor,
m.admin_option
FROM pg_auth_members m
JOIN pg_roles r1 ON m.roleid = r1.oid
JOIN pg_roles r2 ON m.member = r2.oid
JOIN pg_roles r3 ON m.grantor = r3.oid
WHERE r3.rolname = 'admin_user'
ORDER BY r1.rolname, r2.rolname;
「何を直せばいいか」が増えると辛いので、付け替え対象を“機械的にリスト化”するのもおすすめです。例えば、REVOKE文の雛形を作るなら次のように生成できます(実行前に必ずレビューしてください)。
SELECT
format('REVOKE %I FROM %I;', r1.rolname, r2.rolname) AS revoke_sql
FROM pg_auth_members m
JOIN pg_roles r1 ON m.roleid = r1.oid
JOIN pg_roles r2 ON m.member = r2.oid
JOIN pg_roles r3 ON m.grantor = r3.oid
WHERE r3.rolname = 'admin_user';
回避策:grantorをadmin_userから切り離して付け直す
対処の軸はシンプルで、grantorがadmin_userになっているロール付与を、別のgrantorで付け直すことです。ここでは現場で選びやすい2つのパターンを紹介します。
パターン:role1をgrantorに寄せる(最短で現実的)
「role1をrole2へ付与している」なら、可能な範囲でrole1自身をgrantorにするのが分かりやすいです。手順としては、対象の付与を一度剥がして、role1権限で付け直します。
| 作業 | 狙い | 例 |
|---|---|---|
| 現状の付与を剥がす | grantor=admin_userのレコードを消す | REVOKE role1 FROM role2; |
| role1に切り替える | 付与者をrole1にする | SET ROLE role1; |
| 付与し直す | grantor=role1のレコードを作る | GRANT role1 TO role2; |
| ロールを戻す | 事故を防ぐ | RESET ROLE; |
実際のSQLの流れは次のようになります。
-- 例:role1 を role2 に付与しているが、grantor が admin_user になっているケースを付け替える
-- 1) 付与を外す
REVOKE role1 FROM role2;
-- 2) role1 側に切り替える(実行できない場合は、role1のADMINを付けるなど前提整理が必要)
SET ROLE role1;
-- 3) 付与し直す(grantor が role1 になる)
GRANT role1 TO role2;
-- 4) 元に戻す
RESET ROLE;
パターン:ロール付与専用の管理ロールを作る(長期運用向け)
ロール階層が複雑で「role1自身をgrantorにする」が難しい場合は、ロール付与専用の“管理ロール”を用意すると、将来のメンテナンスが楽になります。
- 例:
role_grant_managerのようなロールを作る - このロールに、付与を管理したいロール群のADMINを持たせる
- 以後は、付与作業をこのロールで行い、grantorを一箇所に集約する
イメージ(環境に合わせて調整してください)。
-- 1) 付与管理専用ロールを作る
CREATE ROLE role_grant_manager NOLOGIN;
-- 2) admin_user はこの管理ロールを操作できるようにする(ADMINオプション)
GRANT role_grant_manager TO admin_user WITH ADMIN OPTION;
-- 3) 付与対象のロール(例:role1)のADMINを管理ロールに持たせる
GRANT role1 TO role_grant_manager WITH ADMIN OPTION;
-- 4) 以後は role_grant_manager で付与を実施し、grantor を統一する
SET ROLE role_grant_manager;
GRANT role1 TO role2;
RESET ROLE;
「admin_userが何でも付与してしまう」状態を避け、誰が付与の責任を持つかを構造として表現できるので、監査・運用両面でメリットがあります。
付け替え作業で事故らないための注意点
ロール付与の付け替えは一見単純ですが、権限モデルによってはアプリが一時的に権限を失う可能性があります。実作業では次を意識すると安全です。
- 対象範囲を最小化:まずはgrantor=admin_userの付与だけを対象にする
- アプリ影響の確認:role2がアプリユーザー/アプリロールなら、影響が出る時間帯を避ける
- トランザクションでまとめる:短時間でREVOKE→GRANTが完了するように実行計画を組む
- 作業前後で差分を取る:付与一覧(
pg_auth_members)を作業前後で保存し、復旧できる状態にする
差分確認のために、grantorに関係なくロール付与一覧を出す“棚卸しSQL”も用意しておくと便利です。
SELECT
r1.rolname AS granted_role,
r2.rolname AS member_role,
r3.rolname AS grantor,
m.admin_option
FROM pg_auth_members m
JOIN pg_roles r1 ON m.roleid = r1.oid
JOIN pg_roles r2 ON m.member = r2.oid
JOIN pg_roles r3 ON m.grantor = r3.oid
ORDER BY r1.rolname, r2.rolname, r3.rolname;
サポート依頼時に渡す情報(Tracking IDが最重要)
この障害はサーバー側(Azureバックエンド)で発生しているため、最終的にはサポート側での調査・緩和が必要になります。連絡時は、状況説明だけでなく、調査に必要な情報を揃えると往復が減ります。
| 渡すべき情報 | 具体例 | なぜ必要か |
|---|---|---|
| Tracking ID | エラー画面や通知に出る相関ID | バックエンドのログを紐付けるキー。これが無いと調査が進みにくい |
| 対象サーバー情報 | サーバー名(例:GIS3D)、サブスクリプション、リソースグループ、リージョン | どのリソースで起きたかを一意に特定する |
| 実行した操作 | 「Flexible ServerのMVUでPG17へ」など | 同様の障害を再現できる条件整理に必要 |
| 発生時刻(できればUTCも) | ポータル上の時刻、アクティビティログの時刻 | ログの検索範囲を絞る |
| ロール付与の状況 | grantor=admin_userの一覧(上記SQL結果) | 既知の地雷パターンに該当するか、初動で判断できる |
サポートへは「Tracking IDが出ているInternalServerErrorでMVUが失敗」「azure_pg_adminの仕様変更でgrantor整合性が崩れる可能性がある」「grantor=admin_userの付与が存在する」まで伝えると、話が早くなることが多いです。
MVU前にやっておくと効くチェックリスト
PG17に限らず、メジャーアップグレードは“データの移行”だけではなく“権限モデルの再現”が入ります。Flexible Serverで安定運用したいなら、アップグレード前に次を定型化しておくと事故が減ります。
| チェック項目 | 確認方法 | 狙い |
|---|---|---|
| grantor=admin_userの付与が無いか | pg_auth_membersを検索 | 今回の地雷パターンを事前に潰す |
| ロール階層が複雑すぎないか | ロール図を簡易に書く、または棚卸しSQLで把握 | MVU中に権限再現が難しくなるのを避ける |
| 付与をスクリプト化しているか | DDL/権限付与をGit管理 | 「元に戻す」「作り直す」を最短にする |
| 本番と同等の検証環境でMVUを通したか | ステージングでMVU実行 | バックエンド依存の不具合を早期に踏む |
よくある質問
Tracking IDが分かりません。どこで確認できますか?
ポータルでMVUを実行した直後の通知、失敗した操作の詳細画面、またはリソースのアクティビティログ側に相関IDが残ることがあります。画面上の文言が短い場合でも、詳細を開くとTracking ID相当の情報が見つかることがあります。
admin_userを変更したり作り直したりすると直りますか?
今回の論点は「ユーザー名」そのものより、grantorとして誰が記録されているかです。admin_userを作り直しても、既存の付与レコード(pg_auth_members)が残る限り、根本解決にならないことがあります。まずは付与レコードを棚卸しし、grantorを付け替える方が再現性が高いです。
影響範囲が大きくて付け替えが怖いです
ロール付与が多い環境ほど、「一気に全部」よりもMVUに引っかかりやすい条件(grantor=admin_user)だけを優先的に付け替える方が現実的です。付け替え前後で付与一覧を保存し、いつでも戻せる状態で小さく進めるのが安全です。
まとめ:PG17へのMVUがInternalServerErrorで失敗したら、ロール付与のgrantorを疑う
Azure Database for PostgreSQL Flexible ServerでPG17へのMVUが ResourceOperationFailure / InternalServerError になった場合、データやインデックスより先に、ロール付与の“grantor”情報を疑う価値があります。
- 原因は、Azure側システムロール
azure_pg_adminの挙動変更が、特定のGRANT履歴と衝突すること - 実務上は、Tracking IDを添えてサポートへ連携しつつ、grantor=admin_userの付与を洗い出して付け替えるのが現実的
- 付け替えは「role1をgrantorに寄せる」または「付与管理専用ロールを作る」など、運用しやすい形に寄せる
MVUは一度通れば終わりではなく、次のメジャーアップグレードでも同じ論点が出ます。ロール付与の“誰が付与したか”まで含めて運用を整えると、アップグレード時の不意打ちを減らせます。

コメント