ORA-14452的出現原因解析及解決方法


在刪除臨時表時遇到了ORA-14452錯誤:ORA-14452: attempt to create , alert or drop an index on temporary table already in use。第一次碰到這種情況,問題解決過后,為了加深理解,特意參考網上資料,做了下面實驗重現錯誤出現的場景,以及應該如何解決.


會話級臨時表

由於實驗需要兩個或多個會話配合,所以使用SET SQLPROMPT來標識會話,如下所示,SESSION 1與SESSION 2:


Step 1:在會話1中創建了會話級的臨時表TMP_TEST

 

 

 1 SQL> SET SQLPROMPT "SESSION 1 >"
 2 SESSION 1 >CREATE GLOBAL TEMPORARY TABLE TMP_TEST
 3   2        (  NAME VARCHAR2(12) ) ON COMMIT PRESERVE ROWS;
 4 
 5 Table created.
 6 
 7 SESSION 1 >INSERT INTO TMP_TEST VALUES('Kerry');
 8 
 9 1 row created.
10 
11 SESSION 1 >COMMIT;
12 
13 Commit complete.
14 
15 SESSION 1 >SELECT * FROM TMP_TEST;
16 
17 NAME
18 ------------
19 Kerry

 

 

Step 2:打開另外一個會話2,在這個會話里面操作臨時表TMP_TEST,插入數據。

 1 SQL> SET SQLPROMPT "SESSION 2 >"
 2 SESSION 2 >SELECT * FROM TMP_TEST;
 3 
 4 no rows selected
 5 
 6 SESSION 2 >INSERT INTO TMP_TEST VALUES('Jimmy');
 7 
 8 1 row created.
 9 
10 SESSION 2 >SELECT * FROM TMP_TEST;
11 
12 NAME
13 ------------
14 Jimmy

 


Step 3: 在會話1中刪除臨時表時,就會出現ORA-14452錯誤。

1 SESSION 1 >TRUNCATE TABLE TMP_TEST;
2 
3 Table truncated.
4 
5 SESSION 1 >DROP TABLE TMP_TEST;
6 DROP TABLE TMP_TEST
7            *
8 ERROR at line 1:
9 ORA-14452: attempt to create, alter or drop an index on temporary table already in use

 


Step 4: 如果在會話2中先清空數據,然后去會話1中刪除表則可順利完成

 

1 SESSION 2 >TRUNCATE TABLE TMP_TEST;
2 
3 Table truncated.
4 
5 
6 SESSION 1 >DROP TABLE TMP_TEST;
7 
8 Table dropped.

 

 

 

事務級臨時表


Step 1:  在會話1中創建事務級全局臨時表。 

 

 1 SESSION 1 >CREATE GLOBAL TEMPORARY TABLE TMP_TEST 
 2   2        (  NAME VARCHAR2(12) ) ON COMMIT DELETE ROWS;
 3 
 4 Table created.
 5 
 6 SESSION 1 >INSERT INTO TMP_TEST
 7   2  VALUES('Kerry');
 8 
 9 1 row created.
10 
11 SESSION 1 >SELECT * FROM TMP_TEST;
12 
13 NAME
14 ------------
15 Kerry
16 
17 SESSION 1 >COMMIT; 

 

 

 

Step 2:在會話2中插入一條記錄。

 

1 SESSION 2 >INSERT INTO TMP_TEST VALUES('Jimmy');
2 
3 1 row created.
4 
5 SESSION 2 >SELECT * FROM TMP_TEST;
6 
7 NAME
8 ------------
9 Jimmy

 

 

 

Step 3: 在會話3中刪除全局臨時表時就會報錯 

 1 SESSION 1 >SELECT * FROM TMP_TEST;
 2 
 3 no rows selected
 4 
 5 SESSION 1 >TRUNCATE TABLE TMP_TEST;
 6 
 7 Table truncated.
 8 
 9 SESSION 1 >DROP TABLE TMP_TEST;
10 DROP TABLE TMP_TEST
11            *
12 ERROR at line 1:
13 ORA-14452: attempt to create, alter or drop an index on temporary table already in use

 

 

 

Step 4: 在會話2中提交后,即可在會話1中刪除全局臨時表。

SESSION 2 >COMMIT;

Commit complete.

總結:不管事務級還是會話級的臨時表,都需要所有會話解除綁定,才能DROP,解除綁定的辦法就是清空每個會話的數據.清空數據的辦法:事務級別的臨時表:COMMIT/TRUNCATE TABLE;會話級的臨時表:TRUNCATE TABLE ;但是很多時候,如果出現了這種錯誤,但是我們不知道是那個用戶的那個會話沒有解除綁定,那么此時要如何解決呢?你可以用下面SQL語句來查詢那個會話沒有解除綁定,然后殺掉會話進程。

1 SELECT SID, SERIAL# FROM V$SESSION V 
2   WHERE SID IN (SELECT SID FROM V$LOCK  L, DBA_OBJECTS O 
3             WHERE L.ID1 = O.OBJECT_ID AND O.OBJECT_NAME =UPPER('TMP_TEST')   );
4 
5 ALTER SYSTEM KILL SESSION 'SID, SERIAL#';

 

或者你使用下面步驟一步一步的去定位那個會話沒有解除綁定。

Step 1、先從DBA_OBJECTS/ALL_OBJECTS /USER_OBJECTS中查詢到該表的OBJECT_ID:

    SELECT OBJECT_ID FROM USER_OBJECTS WHERE OBJECT_NAME='TMP_TEST'

Step 2、根據查到的OBJECT_ID知道使用該表的SESSION: 
    SELECT * FROM V$LOCK WHERE ID1=&OBJECT_ID;

Step 3、在從v$session視圖中查到該session的SID和SERIAL#:

    SELECT * FROM V$SESSION WHERE SID=&SID;

Step 4、殺掉這些進程:

  ALTER SYSTEM KILL SESSION 'SID, SERIAL#';


參考資料:

    http://blog.itpub.net/70612/viewspace-1034301/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM