Db2の「SQL0668N 操作は許可されません」を理由コードで即断する ― LOAD後・ALTER後に表が読めない/書けないとき
一括ロードのあと、あるいは ALTER TABLE を流したあと、その表に触ろうとしたら急にこれが返る——SQL0668N「操作は理由コード〜のため許可されません」。SELECTすら弾かれることがあり、「表が壊れた?」と焦りがちですが、ほとんどは表が一時的に制限状態に入っているだけで、理由コードを見れば抜け方は機械的に決まります。
厄介なのは、SQL0668N の理由コードごとに対処がまったく違う点です。「ログ保留だから REORG」と決め打ちすると、実は LOAD の失敗(理由コード3)で、REORG では抜けられない、といったことが起きます。
この記事では、SQL0668N が出たときに理由コードから状態を特定し、正しい抜け方に一直線で進む手順を解説します。
まず結論:SQL0668N は「表が制限状態」。理由コードで状態が確定する
SQL0668N のSQLSTATEは 57007。メッセージには必ず理由コードが付いていて、これで表がどの制限状態にあるかが一意に決まります。
SQL0668N Operation not allowed for reason code "3" on table "MYSCHEMA.SALES".
理由コードは1〜13までありますが、現場で遭遇するのはほぼ次の5つです(全リストは db2 "? SQL0668N" で確認できます)。
| 理由コード | 状態 | どういうとき起きるか | 抜け方 |
|---|---|---|---|
| 3 | Load Pending |
LOAD が失敗して中断した |
LOAD ... RESTART または TERMINATE
|
| 1 | Set Integrity Pending(No Access) |
LOAD 後や制約付き ALTER 後、整合性未検証 |
SET INTEGRITY ... IMMEDIATE CHECKED |
| 4 | Read Access | オンラインLOAD中/後、制約検証前(読取のみ可) |
SET INTEGRITY ... IMMEDIATE CHECKED |
| 7 | Reorg Pending | REORG推奨の ALTER TABLE を重ねた |
REORG TABLE |
| 8 | Alter Pending | 同一UOW内でREORG推奨のALTERをした |
COMMIT する |
まず理由コードを読み、それでも状態を裏取りしたければ、次のクエリでカタログ上の状態を確認します。
ステップ1:表がどの制限状態にあるかを確認する
理由コードだけで判断できるのが理想ですが、複数の状態が絡むときや、そもそもどの表が制限中かを洗い出したいときは SYSCAT.TABLES を見ます。見るべきは3列です。
-- 表の制限状態を確認する
SELECT
VARCHAR(TABNAME,20) AS TAB,
STATUS, -- N=通常 / C=check pending / X=inoperative
ACCESS_MODE, -- F=全アクセス可 / N=不可 / R=読取のみ / D=データ移動不可
SUBSTR(CONST_CHECKED,1,8) AS CONST_CHECKED -- 各制約の検証状態(Y/N/...)
FROM SYSCAT.TABLES
WHERE TABSCHEMA = 'MYSCHEMA'
AND TYPE = 'T';
通常の(制限のない)表はこう見えます。検証環境のSAMPLEの表を例にすると次の通りです。
TAB STATUS ACCESS_MODE CONST_CHECKED
---------------- ------ ----------- -------------
EMPLOYEE N F YYYYYY
DEPARTMENT N F YYYYYY
PROJECT N F YYYYYY
STATUS='N'(通常)・ACCESS_MODE='F'(全アクセス可)・CONST_CHECKED が全て Y なら、その表は制限されていません。SQL0668N の対象表は、ここが次のように変わります。
-
STATUS='C'(check pending)+ACCESS_MODE='N'… 理由コード1(Set Integrity Pending, No Access)。読み書きとも不可。 -
STATUS='C'+ACCESS_MODE='R'… 理由コード4(Read Access)。読取のみ可。 -
CONST_CHECKEDにNが混じる … その制約がまだ検証されていない。SET INTEGRITYで検証すべき対象。
STATUS が check pending 以外(例えばinoperative X)なら別系統の問題です。LOAD 絡みかどうかは LOAD QUERY が最も確実です。
# 表がロード保留/ロード中かを確認する
db2 "LOAD QUERY TABLE MYSCHEMA.SALES"
これで Load pending/Load in progress/Normal のいずれかが分かります。理由コード3か5かの決め手になります。
なお、同じ「触れない」でも、その表だけでなく同じ表スペース上の表がすべて弾かれるなら、原因は表ではなく表スペース側の状態で、返るエラーも SQL0290N になります。この場合は SET INTEGRITY や REORG では抜けられないので、MON_GET_TABLESPACE の TBSP_STATE を先に確認してください。
ステップ2:理由コード別の抜け方
理由コード3(Load Pending)── LOADの失敗が原因
LOAD が途中で失敗すると、表は Load Pending に入り、LOAD を「完了させる」か「無かったことにする」まで一切触れなくなります。REORG でも SET INTEGRITY でも抜けられません。抜け方は2つ。
# 途中まで入ったデータを活かして続きから完了させる
db2 "LOAD FROM /data/sales.del OF DEL RESTART INTO MYSCHEMA.SALES"
# 失敗したLOADを破棄して、LOAD直前の状態に戻す
db2 "LOAD FROM /dev/null OF DEL TERMINATE INTO MYSCHEMA.SALES"
原因(入力ファイルの不正、領域不足など)を直せるなら RESTART、まっさらに戻したいなら TERMINATE です。
理由コード1・4(Set Integrity Pending)── 制約の検証待ち
LOAD(オンラインでない通常ロード)の後や、外部キー・チェック制約を伴う ALTER TABLE ... ADD CONSTRAINT の後、Db2は追加された部分の制約をまだ検証していない状態=Set Integrity Pending に表を置きます。理由コード1は読み書き不可、理由コード4は読取のみ可の違いです。抜け方は共通で SET INTEGRITY です。
# 制約を検証して通常状態に戻す
db2 "SET INTEGRITY FOR MYSCHEMA.SALES IMMEDIATE CHECKED"
このとき、制約に違反する行があると SET INTEGRITY 自体が失敗します。違反行を例外表に逃がしながら検証を通すこともできます。
db2 "SET INTEGRITY FOR MYSCHEMA.SALES IMMEDIATE CHECKED
FOR EXCEPTION IN MYSCHEMA.SALES USE MYSCHEMA.SALES_EXCEPTION"
理由コード7(Reorg Pending)── ALTERの積み重ねが原因
ALTER TABLE で列のサイズ変更などREORG推奨の変更を(1つのUOW内で3回など)重ねると、表が Reorg Pending に入り、REORG するまで使えなくなります。
db2 "REORG TABLE MYSCHEMA.SALES"
なお Reorg Pending の表はインプレースREORG(INPLACE)では抜けられません。通常の(オフライン)REORG TABLE を使います。
理由コード8(Alter Pending)── コミットで抜ける
同一トランザクション内でREORG推奨の ALTER をした直後にその表へアクセスすると理由コード8になります。これは単にその作業単位をコミットすれば解消します。
db2 "COMMIT"
SQL0668N が出たときのチェックリスト
- メッセージの理由コードを読む(
db2 "? SQL0668N"で全リスト) - 迷ったら
SYSCAT.TABLESのSTATUS/ACCESS_MODE/CONST_CHECKEDで状態を裏取り -
LOAD絡みが疑わしければLOAD QUERY TABLE ...で Load pending / in progress を確認 -
理由3(Load Pending)…
LOAD ... RESTARTかTERMINATEで後始末(REORGでは抜けない) -
理由1・4(Set Integrity Pending)…
SET INTEGRITY ... IMMEDIATE CHECKED。違反行は例外表へ -
理由7(Reorg Pending)… オフライン
REORG TABLE(INPLACE不可) -
理由8(Alter Pending)…
COMMIT - 恒久対策は「LOAD失敗時の後始末を手順化」+「制約付きALTER/LOAD後の
SET INTEGRITYをジョブに組み込む」
📕 もっと深く:Db2運用を12章で体系化した本を書きました
この記事で扱った SQL0668N の切り分けは、Db2運用のほんの一部です。
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ——そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にしました。実機で検証した内容と、Db2の設計上そうなる理由をまとめました。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORGを意図して制御する/MON_GET監視/現場の難題・解決集まで、全12章+運用シェルスクリプト集です。
Db2の運用で踏んだ地雷や、扱ってほしいテーマがあれば、ぜひコメントで教えてください。次の記事のネタにさせてもらいます。
Discussion