Db2の「SQL0551N 権限がありません」は“誰が・何を・どのオブジェクトに”を読んで最短で潰す
SQL0551N「認可IDに必要な権限がありません」は、開発中でも本番リリース直後でも遭遇率の高いエラーです。原因は「権限が足りない」のひと言なのですが、現場で時間を取られるのは本当に権限が無いのか、それとも思っている認可ID・スキーマと違うIDで実行しているのかの切り分けです。
GRANT を追加する前に確認すべきことがあります。「権限が無い」と思って手当たり次第に GRANT を積むと、最小権限の原則が崩れ、後で棚卸しができなくなります。まずメッセージを正しく読み、足りない権限を一点だけ特定してから付与するのが正攻法です。
この記事では、SQL0551N が出たときにメッセージの3つのトークンから原因を切り分け、必要な権限だけを付与する手順を解説します。
まず結論:SQL0551N は「認可ID・操作・オブジェクト」の3点で原因が絞れる
SQL0551N の SQLSTATE は 42501。Db2 12.1 のメッセージは、原因特定に必要な3つのトークンを明示します。
SQL0551N The statement failed because the authorization ID does not
have the required authorization or privilege to perform the operation.
Authorization ID: "APPUSER". Operation: "SELECT". Object: "SALES.ORDERS".
読むべきは3つです。
- Authorization ID … 実際にその文を実行している認可ID。これが「自分が思っているID」と違うことが多い
-
Operation … 足りない権限の種類(
SELECT/INSERT/EXECUTE/ALTER/REFERENCESなど) -
Object … 対象オブジェクト。スキーマ修飾まで見る(
SALES.ORDERSなのか、意図せずAPPUSER.ORDERSを見に行っていないか)
切り分けの順序はこうです。
- 認可IDとオブジェクト名(スキーマ)が想定どおりか を確認する(ここがズレている“権限ではない”ケースが最多)
- 想定どおりなら、その認可IDが本当に権限を持っていないかを カタログで確認
- 足りない一点だけを
GRANTする(ロール/グループ経由で入れるべきかも判断)
ステップ1:まず「別のID・別スキーマで動いていないか」を疑う
SQL0551N の相当数は、権限の付与漏れではなく実行しているIDやスキーマの取り違えです。付与を足す前にここを潰します。現在の認可IDと既定スキーマを確認します。
VALUES (CURRENT USER, CURRENT SCHEMA);
1 2
--------- ---------
DB2INST1 DB2INST1
よくある取り違えは次の3つです。
- 接続ユーザーが想定と違う。 アプリの接続文字列やデータソースが別のIDで繋いでいる。メッセージの Authorization ID が「開発者個人ではなくアプリ共通ID」になっていないか。
-
スキーマ修飾の漏れ。
SELECT * FROM ORDERSと非修飾で書くと、CURRENT SCHEMA(既定は接続ID)で解決される。APPUSERで繋いでいればAPPUSER.ORDERSを探しに行き、本来見たいSALES.ORDERSとは別物になる。メッセージの Object のスキーマが想定と違えばこれ。 -
静的SQL(パッケージ)の実行権限。 埋め込みSQLやストアドの実体はパッケージで、実行には
EXECUTE権限が要る。表への直接権限があってもパッケージのEXECUTEが無いと弾かれる。
ここで原因が「取り違え」だと分かれば、スキーマ修飾を直す・正しいIDで繋ぐだけで解消し、GRANT は不要です。
ステップ2:認可IDが持っている権限をカタログで確認する
取り違えでないなら、その認可IDの権限を確認します。オブジェクト単位の権限は SYSCAT.TABAUTH を見ます。
-- 表 SALES.ORDERS に対する権限保持者
SELECT SUBSTR(GRANTEE,1,12) AS GRANTEE, GRANTEETYPE,
SELECTAUTH, INSERTAUTH, UPDATEAUTH, DELETEAUTH
FROM SYSCAT.TABAUTH
WHERE TABSCHEMA = 'SALES' AND TABNAME = 'ORDERS';
GRANTEE GRANTEETYPE SELECTAUTH INSERTAUTH UPDATEAUTH DELETEAUTH
------------ ----------- ---------- ---------- ---------- ----------
DB2INST1 U G G G G
読み方は次のとおりです。
-
GRANTEETYPE …
U=ユーザー /G=グループ /R=ロール。問題のIDが直接持っていなくても、所属グループやロール経由で持っていることがある点に注意。 -
各AUTH列 …
Y=保持 /G=保持かつ他者へ付与可(WITH GRANT OPTION)/N=なし。
その認可IDが持つデータベース権限・管理権限は SYSCAT.DBAUTH と、まとめて見るなら表関数 AUTH_LIST_AUTHORITIES_FOR_AUTHID が便利です。
-- 認可ID DB2INST1 が持つ権限(直接付与されているものを抽出)
SELECT SUBSTR(AUTHORITY,1,22) AS AUTHORITY, D_USER, D_GROUP, D_ROLE
FROM TABLE(SYSPROC.AUTH_LIST_AUTHORITIES_FOR_AUTHID('DB2INST1','U'))
WHERE D_USER = 'Y' OR D_GROUP = 'Y' OR D_ROLE = 'Y';
AUTHORITY D_USER D_GROUP D_ROLE
---------------------- ------ ------- ------
DBADM Y N *
SECADM Y N *
DATAACCESS Y N *
ACCESSCTRL Y N *
D_USER/D_GROUP/D_ROLE は、その権限を直接(Directly)どの経路で持っているかを示します。DATAACCESS を持っていれば全表の読み書きができる、といった上位権限の有無もここで分かります。
ロール経由の権限を追うときは SYSCAT.ROLEAUTH でロールの所属を確認します。
SELECT SUBSTR(GRANTEE,1,12) AS GRANTEE, GRANTEETYPE, SUBSTR(ROLENAME,1,16) AS ROLENAME
FROM SYSCAT.ROLEAUTH
WHERE GRANTEE = 'APPUSER';
ステップ3:足りない権限“だけ”を付与する
原因が権限不足だと確定したら、メッセージの Operation に対応する権限を一点だけ GRANT します。
-- 表への SELECT だけを付与
GRANT SELECT ON SALES.ORDERS TO USER APPUSER;
-- 静的SQL/CLIパッケージの EXECUTE 不足なら
GRANT EXECUTE ON PACKAGE APPSCHEMA.PKG01 TO USER APPUSER;
-- 参照制約の作成に必要な REFERENCES 不足なら(メッセージ Operation が REFERENCES)
GRANT REFERENCES ON SALES.CUSTOMER TO USER APPUSER;
個々のオブジェクトではなく役割としてまとめて渡したいなら、ロールを作って権限をロールに集約し、ユーザーはロールに入れます。個人IDへ直接 GRANT を積むより棚卸ししやすくなります。
CREATE ROLE APP_RO; -- 参照専用ロール
GRANT SELECT ON SALES.ORDERS TO ROLE APP_RO;
GRANT ROLE APP_RO TO USER APPUSER;
現場で効く注意点
-
グループ/ロール経由を見落とさない。 直接
GRANTされていなくても、OSグループやロール経由で権限を持つ/失うことがあります。GRANTEETYPE(U/G/R)を必ず確認し、SYSCAT.ROLEAUTHでロール所属も追います。 -
静的SQLは「パッケージのBIND者」の権限で動く。 埋め込みSQLやストアドは、実行ユーザーではなくBINDした所有者の権限で解決されることがあります。「表権限はあるのに
SQL0551N」なら、パッケージのEXECUTE権限や、REBIND/再BINDが必要なケース(公式メッセージのシナリオ2)を疑います。 -
REVOKEは依存オブジェクトに波及する。 ある権限を剥がすと、それに依存していたビューやパッケージが無効化され、別の場所でSQL0551Nが出ることがあります。剥がす前に依存関係を確認します。 -
メッセージのトークン表記はバージョンで変わる。 旧バージョンでは
"APPUSER" does not have the privilege to perform operation "SELECT" on object "SALES.ORDERS"のような表記です。読む要素(誰が・何を・どのオブジェクトに)は同じです。
SQL0551N が出たときのチェックリスト
- メッセージの Authorization ID / Operation / Object を読む(SQLSTATEは
42501) -
取り違えを先に疑う …
VALUES (CURRENT USER, CURRENT SCHEMA)で実行ID・既定スキーマを確認。Object のスキーマ修飾が想定どおりか - 取り違えでなければ
SYSCAT.TABAUTHでそのオブジェクトの権限保持者とGRANTEETYPE(U/G/R)・保持状況(Y/G/N)を確認 - DB権限・管理権限は
SYSCAT.DBAUTH/AUTH_LIST_AUTHORITIES_FOR_AUTHID、ロールはSYSCAT.ROLEAUTH - 足りない Operation の権限だけ を
GRANT(役割ならロールに集約) - 「表権限はあるのに弾かれる」ならパッケージの
EXECUTE/再BINDを疑う -
DATAACCESS/DBADMの安易な付与で消さない(被害範囲と監査の観点)
📕 もっと深く:Db2運用を12章で体系化した本を書きました
この記事で扱った SQL0551N と権限設計は、Db2運用のほんの一部です。
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ——そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にしました。実機で検証した内容と、Db2の設計上そうなる理由をまとめました。
認証・暗号化・権限設計をまとめた**第3章「セキュリティ設計の基本と実装」**をはじめ、アーキテクチャ/構成パラメーター選定/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題・解決集まで、全12章+運用シェルスクリプト集です。
Db2の運用で踏んだ地雷や、扱ってほしいテーマがあれば、ぜひコメントで教えてください。次の記事のネタにさせてもらいます。
Discussion