Oracle 10g 以降、DROP TABLE を実行してもテーブルは即座に削除されません。代わりにリサイクルビン(Recycle Bin)と呼ばれる一時保管領域に移動され、FLASHBACK DROP を使って元に戻せます。
誤って重要なテーブルを削除してしまった場合に役立つ機能ですが、リサイクルビンに蓄積された BIN$ から始まるオブジェクトが表領域を占有したり、名前が衝突したりと、思わぬトラブルの原因にもなります。
この記事でわかること
- リサイクルビンの仕組みと BIN$ 命名規則
- USER_RECYCLEBIN / DBA_RECYCLEBIN でリサイクルビンの内容を確認する方法
- FLASHBACK TABLE … TO BEFORE DROP でテーブルを復元する方法
- PURGE TABLE / PURGE RECYCLEBIN で完全削除する方法
- DROP TABLE … PURGE で即時完全削除する方法
- RECYCLEBIN パラメータでリサイクルビン機能をオフにする方法
リサイクルビンの仕組み
DROP TABLE を実行すると、テーブルはリサイクルビンに移動し、オブジェクト名が BIN$ で始まる一意な名前に変換されます。テーブルが使用していた表領域のセグメントはそのまま保持されるため、リサイクルビンの内容が増えると表領域を圧迫します。
リサイクルビンの基本動作を確認する
-- テーブルを作成して削除する
CREATE TABLE test_orders (
order_id NUMBER PRIMARY KEY,
item_name VARCHAR2(100),
amount NUMBER
);
INSERT INTO test_orders VALUES (1, 'Widget', 1000);
COMMIT;
DROP TABLE test_orders; -- ← テーブルはリサイクルビンへ移動する
-- テーブルを参照しようとするとエラーになる
SELECT * FROM test_orders;
-- ORA-00942: 表またはビューが存在しません
-- ただし BIN$ 名で参照できる
SELECT * FROM "BIN$...===$0"; -- BIN$ 名で参照可能(BIN$ 名は USER_RECYCLEBIN で確認)
-- USER_RECYCLEBIN でリサイクルビンの内容を確認する
SELECT
object_name, -- BIN$ から始まるリサイクルビン内の名前
original_name, -- DROP 前のオリジナルの名前
type, -- TABLE, INDEX, TRIGGER など
ts_name, -- 表領域名
createtime, -- オブジェクトの作成日時
droptime, -- DROP した日時
space -- 使用ブロック数
FROM USER_RECYCLEBIN
ORDER BY droptime DESC;
リサイクルビンに入るオブジェクトと入らないオブジェクト
- 入る:通常の表(ユーザーが所有するテーブル)とそれに関連するインデックス・トリガー・制約
- 入らない:SYSTEM 表領域のテーブル・パーティションテーブルの親(パーティションごとには入る)・クラスタの一部のテーブル・マテリアライズドビューログを持つテーブル
- 外部キー(FK)制約が残っているとリサイクルビンに入らず即時削除される場合がある
FLASHBACK DROP でテーブルを復元する
FLASHBACK TABLE … TO BEFORE DROP の使い方
-- テーブルをオリジナルの名前で復元する FLASHBACK TABLE test_orders TO BEFORE DROP; -- 復元後にテーブルを確認する SELECT * FROM test_orders; -- オリジナル名で参照できる -- 同名のテーブルが既に存在する場合: RENAME TO で別名を指定して復元する -- (同名テーブルが既に存在するとそのままでは復元できない) FLASHBACK TABLE test_orders TO BEFORE DROP RENAME TO test_orders_restored; -- リサイクルビンに同名テーブルが複数ある場合(複数回 DROP した場合): -- USER_RECYCLEBIN で確認して BIN$ 名で特定のバージョンを指定する SELECT object_name, original_name, droptime FROM USER_RECYCLEBIN WHERE original_name = 'TEST_ORDERS' ORDER BY droptime DESC; -- BIN$ 名を使って特定のバージョンを復元する(最新以外を復元したい場合) FLASHBACK TABLE "BIN$abc123xyz===$0" TO BEFORE DROP RENAME TO test_orders_v1; -- インデックスも一緒に復元されるが、インデックス名は BIN$ のままになる -- 復元後にインデックスを確認して RENAME する SELECT index_name FROM USER_INDEXES WHERE table_name = 'TEST_ORDERS'; ALTER INDEX "BIN$...===$0" RENAME TO test_orders_pk;
PURGE でリサイクルビンからオブジェクトを完全削除する
PURGE コマンドの各種使い方
-- 特定テーブルをリサイクルビンから完全削除する(オリジナル名で指定)
PURGE TABLE test_orders;
-- BIN$ 名で指定する(同名テーブルが複数ある場合に使う)
PURGE TABLE "BIN$abc123xyz===$0";
-- 現在のユーザーのリサイクルビンをすべてクリアする
PURGE RECYCLEBIN;
-- PURGE USER_RECYCLEBIN; も同義
-- すべてのユーザーのリサイクルビンをクリアする(DBA 権限が必要)
PURGE DBA_RECYCLEBIN;
-- 特定の表領域に属するオブジェクトをリサイクルビンからクリアする(DBA 権限)
PURGE TABLESPACE users;
-- 特定ユーザーの指定表領域のみクリアする
PURGE TABLESPACE users USER app_user;
-- リサイクルビンの内容を一覧して占有サイズを確認する(DBA 権限)
SELECT
owner,
original_name,
type,
ts_name,
SUM(space) * 8192 / 1024 / 1024 AS size_mb -- ブロック数 → MB に変換
FROM DBA_RECYCLEBIN
GROUP BY owner, original_name, type, ts_name
ORDER BY size_mb DESC;
DROP TABLE … PURGE で即時完全削除する
リサイクルビンをバイパスして即時削除する
-- DROP TABLE ... PURGE: リサイクルビンを経由せずに即時完全削除する DROP TABLE test_orders PURGE; -- DROP 後に SELECT すると ORA-00942 になる(BIN$ 名でも参照不可) SELECT * FROM test_orders; -- ORA-00942: 表またはビューが存在しません -- DROP TABLE ... PURGE は FLASHBACK DROP で復元できないため注意 -- 本番環境での重要テーブルの削除は PURGE なしで行い、確認後に PURGE する -- INDEX も同様に PURGE オプションがある DROP INDEX emp_salary_idx PURGE;
リサイクルビンを無効にする
RECYCLEBIN パラメータでリサイクルビンをオフにする
-- 現在の設定を確認する SHOW PARAMETER recyclebin; -- recyclebin = on (デフォルト) -- セッション単位で無効にする ALTER SESSION SET RECYCLEBIN = OFF; -- このセッションの DROP TABLE はリサイクルビンを経由せず即時削除になる -- システム全体で無効にする(DBA 権限が必要) ALTER SYSTEM SET RECYCLEBIN = OFF; -- 設定後の DROP TABLE は即時削除になる。既存のリサイクルビン内容は残る -- リサイクルビン内の既存オブジェクトをクリアしてから無効にするのが推奨 PURGE DBA_RECYCLEBIN; ALTER SYSTEM SET RECYCLEBIN = OFF; -- 注意: RECYCLEBIN = OFF でも既にリサイクルビンに入っているオブジェクトは残る -- PURGE DBA_RECYCLEBIN で明示的にクリアする必要がある
リサイクルビン関連のよくあるトラブル
| 症状 | 原因 | 対処法 |
|---|---|---|
| 表領域の空き不足なのに使用中のテーブルは少ない | リサイクルビンが表領域を占有している | PURGE TABLESPACE xxx または PURGE DBA_RECYCLEBIN |
| BIN$ で始まるインデックスが大量にある | DROP TABLE で不要なインデックスがリサイクルビンに残っている | PURGE RECYCLEBIN でクリアする |
| DROP TABLE 後に同名テーブルを CREATE できない | リサイクルビンに同名のオブジェクトがあっても CREATE 自体は可能(別名保存される) | 問題なし。リサイクルビン内の同名オブジェクトは古いバージョンとして共存する |
| FLASHBACK TABLE が失敗する | リサイクルビンからすでに PURGE 済み・または表領域の空き不足 | USER_RECYCLEBIN を確認。空き不足なら表領域を拡張する |
| SELECT FROM BIN$ テーブルで ORA-00942 | BIN$ 名を二重引用符で囲んでいない | SELECT * FROM "BIN$abc..." と二重引用符を使う |
まとめ
- リサイクルビン:DROP TABLE したテーブルは即削除されず BIN$ 名でリサイクルビンに保管される。FLASHBACK DROP で復元可能
- FLASHBACK TABLE … TO BEFORE DROP:オリジナル名または BIN$ 名を指定して復元。同名テーブルが既に存在する場合は RENAME TO で別名を指定する
- USER_RECYCLEBIN:自分のリサイクルビン内容を確認。DBA_RECYCLEBIN で全ユーザー分を確認(DBA権限必要)
- PURGE RECYCLEBIN:自分のリサイクルビンをすべてクリア。PURGE DBA_RECYCLEBIN で全ユーザー分(DBA権限)
- DROP TABLE … PURGE:リサイクルビンをバイパスして即時完全削除。FLASHBACK DROP では復元不可
- RECYCLEBIN = OFF:リサイクルビン機能を無効にする。表領域の節約やスキーマ管理がシンプルになるが、誤削除の復元はできなくなる
DROP TABLE を含む DDL の変更管理には Oracle Flashback 完全ガイド(AS OF TIMESTAMP・Flashback Table)も参照してください。表領域の空き不足トラブルへの対処は Oracle 容量不足の緊急対応ガイドも参照してください。