目前統計異常:ORA-00000、ORA-00001、ORA-00017、ORA-00018、ORA-00019、ORA-00020、ORA-01722、ORA-01747 文檔通過翻譯文檔、搜索資料及測試實踐對Oralce的異常做彙總、分析導致異常的各類原因及對應的解決方法,並備註一些知識點以助學... ...
持續更新中,可參見https://hnuhell.gitbooks.io/oracle_errmg/content/或https://hnuhell.github.io/Oracle_ERRMG/上的頁面。
ORA-00000 to ORA-00877
ORA-00000: 正常的成功的完成(操作)
ORA-00000: normal, successful completion
原因1: 正常執行完成。【部分驗證】
Normal exit.
- 分析: 此異常多數為程式沒有執行SQL語句或者說成功執行完SQL語句,但人為或因邏輯有誤,非要使用相關方法程式去獲取Oracle的錯誤信息,得到此異常,實質是Oracle告知沒有異常產生,猜測是異常信息的預設值為這個。目前發現以下兩種情況:
-
存儲過程、PL/SQL塊等,使用sqlerrm獲取異常,如下例所示。【已驗證】
declare v_sqlcode number; v_sqlerrm varchar2(4000); begin /* …… 相關執行代碼 …… */ v_sqlcode := sqlcode; v_sqlerrm := sqlerrm; dbms_output.put_line('本次的異常code:' || v_sqlcode || chr(10) || '本次的異常信息:' || v_sqlerrm); exception when others then rollback; v_sqlcode := sqlcode; v_sqlerrm := sqlerrm; dbms_output.put_line('本次的異常code:' || v_sqlcode || chr(10) || '本次的異常信息:' || v_sqlerrm); end; /
-
使用OCI的C程式中,用erhms()函數(OCIErrorGet())獲得Oracle錯誤信息。【未驗證,網路彙總】
-
-
措施: 無。【如果是人為需要獲取該異常,則不用做任何操作;如果是邏輯有誤,那麼需要調整不去此異常或者在遇到此異常時將其屏蔽去掉。】
None
原因2: hosts文件配置錯誤。【未驗證,網路彙總】
- 分析: 這種錯誤通常由於資料庫是複製過來的,hosts文件中的ip對應的host name和當前的主機名不一致導致甚至hosts文件丟失,都會導致資料庫startup時報此錯。
- 措施: 校驗hosts文件是否有錯或缺失,進行修改或補充。
-
hosts文件在不同系統中所處的目錄:
Windows XP/2000/Vista/7/8/8.1/10 ==> C:\windows\system32\drivers\etc\ Linux及其他類Unix操作系統 ==> /etc/
-
ORA-00001: 違反唯一約束條件 (string.string=>[擁有者].[約束名])
ORA-00001: unique constraint (string.string) violated
原因1: UPDATE或INSERT語句試圖插入重覆的鍵。對於在DBMS MAC模式下配置的Trusted Oracle,如果在不同級別存在重覆條目,您可能會看到此信息。【已驗證】
An UPDATE or INSERT statement attempted to insert a duplicate key. For Trusted Oracle configured in DBMS MAC mode, you may see this message if a duplicate entry exists at a different level.
-
分析: 如下例所示,此異常一般為違反作用於表上的唯一約束或者主鍵約束導致,它們限制了表的一列或多列值的唯一性,不能插入重覆數據。
-- 創建測試表 create table ora_00001_1( a char(24) /*primary key*/, -- 亦可加註釋內信息實現添加主鍵約束 b number /*unique*/, -- 亦可加註釋內信息實現添加唯一約束 -- 增加主鍵約束 constraint ora_00001_1_a primary key (a) -- 亦可加註釋內信息實現添加唯一約束 /*, constraint ora_00001_1_b unique (b)*/ ); -- 亦可加註釋內信息實現添加主鍵約束 /*alter table ora_00001_1 add constraint ora_00001_1_a primary key (a);*/ -- 增加唯一約束 alter table ora_00001_1 add constraint ora_00001_1_b unique (b); -- 插入測試數據 insert into ora_00001_1(a, b) values ('1',1); insert into ora_00001_1(a, b) values ('2',2); commit; -- ORA-00001: 違反唯一約束條件 (C##LY.ORA_00001_1_A); insert into ora_00001_1(a, b) values ('1',3); -- ORA-00001: 違反唯一約束條件 (C##LY.ORA_00001_1_B) insert into ora_00001_1(a, b) values ('3',2); -- ORA-00001: 違反唯一約束條件 (C##LY.ORA_00001_1_A) update ora_00001_1 set a = '1' where a = '2'; -- ORA-00001: 違反唯一約束條件 (C##LY.ORA_00001_1_B) update ora_00001_1 set b = '2' where b = '1';
-
措施: 刪除唯一約束限制或不插入重覆值。
Either remove the unique restriction or do not insert the key.
-
如果分析確定此處唯一約束或主鍵約束不需要,那麼則可使用下麵語句刪除約束
-- 查詢約束與索引信息 select a.owner 約束所有者, a.constraint_name 約束名, case a.constraint_type when 'P' then 'Primary key' when 'U' then 'Unique key' when 'C' then ' Check constraint on a table' when 'R' then 'Referential integrity' when 'V' then 'With check option, on a view' when 'O' then 'With read only, on a view' when 'H' then 'Hash expression' when 'F' then 'Constraint that involves a REF column' when 'S' then 'Supplemental logging' else 'unkown' end 約束類型, b.table_name 表名, b.column_name 列名, c.index_name 索引名, c.uniqueness 是否唯一索引/*, d.table_name 表名, d.column_name 列名*/ from user_constraints a, user_cons_columns b, user_indexes c/*, user_ind_columns d*/ where a.constraint_name = b.constraint_name and a.index_name = c.index_name /*and c.index_name = d.index_name*/ and a.owner = b.owner and a.owner = c.table_owner and a.owner = &"[擁有者]" and a.constraint_name = &"[約束名]"; -- 由於如果約束對應的唯一索引若是事先手工創建的,那麼在刪除約束時索引不會被刪除,Oracle之後自動刪除自己隱式創建的索引。 -- 因此加上drop index,可確保一定將索引刪除。 alter table [表名] drop constraint [約束名] drop index; -- 如果是主鍵約束,有可能遇到有用作外鍵的情況,那麼在刪除時仍會報=>ORA-02273: 此唯一/主鍵已被某些外鍵引用 -- 報錯後瞭解是否有問題,是否需去除此主鍵和外鍵,然後可考慮用下麵語句刪除主鍵約束,會同時刪除外鍵約束 alter table [表名] drop constraint [約束名] cascade drop index; alter table [表名] drop primary key cascade drop index;
-
如果分析確定是值重覆,那麼需排查表數據與預執行的SQL語句的重覆值衝突、同一個事務內執行的SQL語句之間的重覆值衝突,去掉重覆值的插入或更新。
-
-
備註:
- 唯一約束與主鍵約束的同:
- 都通過唯一索引來限制約束列的唯一性,確保任何使表中約束的列在行與行之間存在重覆值的操作失敗
- 若無事先創建好唯一索引,都會在創建唯一約束或主鍵約束時隱式創建同名的唯一約束
- 有約束必定有索引(無法在保持約束存在的情況下刪除索引=>ORA-02429: 無法刪除用於強制唯一/主鍵的索引)
- 有索引不一定有約束(只刪除約束但不刪除索引則仍然會限制索引列的值的唯一性)
- 唯一約束與主鍵約束的異:
- 唯一約束允許在該列或多列上存在NULL值,但主鍵約束不能存在NULL值
- 一個表只能創建一個主鍵約束,但可創建多個唯一約束
- 主鍵可擴展作為外鍵,唯一約束不可
- 唯一約束與主鍵約束的同:
ORA-00017: 會話被要求設置跟蹤事件
ORA-00017: session requested to set trace event
原因1: 當前會話被要求通過另一個會話設置一個跟蹤事件【ora12_ERRMG】
The current session was requested to set a trace event by another session.
-
措施: 內部使用;無需操作。
This is used internally; no action is required.
ORA-00018: 超出最大會話數
ORA-00018: maximum number of sessions exceeded
原因1: 所有會話狀態對象都在使用中。【部分驗證】
All session state objects are in use.
- 分析: 很明顯,系統中所有會話數目已經達到設置的SESSIONS值,因此準備要創建的會話無法成功創建,而這個會話包括有用戶建立連接至資料庫是產生的會話、後臺進程產生的會話以及各類涉及到硬解析處理數據字典基表的DML、DDL語句產生的遞歸會話。
-
措施: 增加SESSIONS初始化參數值。【是否需要增加SESSIONS值還需進行判斷,是否是由於此值過小而現實場景需要更大的值?】
Increase the value of the SESSIONS initialization parameter.
-
如果判斷確定是由於SESSIONS值過小導致,則需修改增大此參數值:
/* alter system set 參數名=值 [scope=應用範圍]; scope需知: scope=both,表示修改會立即生效且會修改spfile文件以確保資料庫在重啟後也會生效如果(以spfile啟動此項為預設值); scope=memory,表示修改會立即生效但不會修改spfile文件,因此重啟後失效(以pfile啟動此項為預設值,且只可設置這個值); scope=spfile,表示只修改spfile文件,在重啟資料庫後才生效(對應靜態參數則只可設置此項值,設置其它值會報錯: ORA-02095: specified initialization parameter cannot be modified)。 */ -- 查看"是否可用ALTER SYSTEM修改"列值,根據結果進行修改 select name 參數名, case type when 1 then 'Boolean' when 2 then 'String' when 3 then 'Integer' when 4 then 'Parameter file' when 5 then 'Reserved' when 6 then 'Big integer' else 'unknown' end 參數類型, value "會話級(若可修改)或實例級參數值", display_value 展示值, isses_modifiable "是否可用ALTER SESSION修改", case issys_modifiable when 'IMMEDIATE' then '無論pfile還是spfile啟動,都可用"alter system set ' || name || '=&' || '新的參數值;"更改參數並立即生效。' when 'DEFERRED' then '無論pfile還是spfile啟動,都可用"alter system set ' || name || '=&' || '新的參數值;"更改參數並將在之後的會話中生效。' when 'FALSE' then case a.is_spfile when 0 then '使用pfile啟動,需手動修改pfile文件中對應參數值再重啟。' else '使用spfile啟動,可用"alter system set ' || name || '=&' || name || ' scope=spfile;"更改參數。更改將在後續的實例中生效(當前資料庫需重啟)。' end else '?' end "是否可用ALTER SYSTEM修改", isinstance_modifiable "是否不同實例間值可不同" from v$parameter, (select count(1) is_spfile from v$parameter t where t.name = 'spfile') a where name = 'sessions';
-
如果判斷確定SESSIONS值合理,則需分析確定產生大量會話的原因,是否相關程式代碼建立了連接未釋放?或者其它原因等。【待完善】
-
-
備註: 參數SESSIONS:
屬性 描述 參數類型 Integer 預設值 派生公式: (1.1 * PROCESSES) + 5) [11gR1,11gR2]
(1.5 * PROCESSES) + 22可修改(不用重啟及時生效) 否 [11gR2,12cR1]
可用ALTER SYSTEM修改取值範圍 1~2^31 [11gR1,11gR2]
1~2^16(1~65536)基礎參數 是 SESSIONS指定可以在系統中創建的最大會話數。因為每次登錄都需要一個會話,所以這個參數有效地確定了系統中最大併發用戶數。您應該始終將此參數顯式設置等於最大併發用戶數的估計值+後臺進程數+遞歸會話數(大約占總數的10%)。
Oracle使用此參數的預設值作為其最小值。 將SESSIONS值設置成[1~預設值)不會觸發錯誤,因為Oracle會忽略此值直接使用預設值。
ENQUEUE_RESOURCES和TRANSACTIONS參數的預設值派生自SESSIONS。因此,如果增加SESSIONS的值,則應考慮是否也調整ENQUEUE_RESOURCES和TRANSACTIONS的值。 (請註意,從Oracle Database 10g release 2(10.2)起,ENQUEUE_RESOURCES已被廢棄。)
在共用伺服器環境中,PROCESSES的值可能相當小。因此,Oracle建議您將SESSIONS的值調整為大約1.1 *總連接數。
ORA-00019: 超出最大許可會話數
ORA-00019: maximum number of session licenses exceeded
原因1: 所有許可會話都在使用中。【部分驗證】
All licenses are in use.
- 分析: 很明顯,系統中併發用戶會話已經達到設置的LICENSE_MAX_SESSIONS值,因此準備要創建的用戶會話無法創建。
-
措施: 增大LICENSE_MAX_SESSIONS初始化參數的值。【是否需要增加LICENSE_MAX_SESSIONS值還需進行判斷,是否是由於此值過小而現實場景需要更大的值?】
Increase the value of the LICENSE MAX SESSIONS initialization parameter.
- 如果判斷確定是由於LICENSE_MAX_SESSIONS值過小導致,則需修改增大此參數值,【詳情參見ORA-00018=>原因1=>措施,將SQL語句中
name = 'sessions'
修改為name = 'license_max_sessions'
即可】 - 如果判斷確定LICENSE_MAX_SESSIONS值合理,則需分析確定產生大量會話的原因,是否相關程式代碼建立了連接未釋放?或者其它原因等。【待完善】
- 如果判斷確定是由於LICENSE_MAX_SESSIONS值過小導致,則需修改增大此參數值,【詳情參見ORA-00018=>原因1=>措施,將SQL語句中
-
備註: 參數LICENSE_MAX_SESSIONS:
屬性 描述 參數類型 Integer 預設值 0 可修改(不用重啟及時生效) 可用ALTER SYSTEM修改 取值範圍 0~許可會話數 基礎參數 否 Oracle實時應用集群 多個實例可以具有不同的值,但是安裝資料庫的所有實例的總和應小於或等於該資料庫許可的會話總數。 LICENSE_MAX_SESSIONS指定允許的併發用戶會話的最大數量。達到此限制後,只有具有RESTRICTED SESSION許可權的用戶才能連接到資料庫。無法連接的用戶收到表示系統達到最大容量的警告消息。
零值表示不強制執行併發使用(會話)許可。如果將此參數設置為非零數字,則可能還需要設置LICENSE_SESSIONS_WARNING(請參閱“LICENSE_SESSIONS_WARNING”)。
不要同時啟用併發使用許可和用戶許可,即LICENSE_MAX_SESSIONS與LICENSE_MAX_USERS兩參數值至少一個要設置為零。
ORA-00020: 超出最大進程數(string=>[最大進程數])
ORA-00020: maximum number of processes (string) exceeded
原因1: 所有進程狀態對象都在使用中。【部分驗證】
All process state objects are in use.
- 分析: 很明顯,系統中進程數已經達到設置的PROCESSES值,因此準備要創建的用戶會話無法創建。
-
措施: 增加PROCESSES初始化參數的值。【是否需要增加PROCESSES值還需進行判斷,是否是由於此值過小而現實場景需要更大的值?】
Increase the value of the PROCESSES initialization parameter.
- 如果判斷確定是由於PROCESSES值過小導致,則需修改增大此參數值,【詳情參見ORA-00018=>原因1=>措施,將SQL語句中
name = 'sessions'
修改為name = 'processes'
即可】 - 如果判斷確定PROCESSES值合理,則需分析確定產生大量進程的原因,是否相關程式代碼建立了連接未釋放?或者其它原因等。【待完善】
- 如果判斷確定是由於PROCESSES值過小導致,則需修改增大此參數值,【詳情參見ORA-00018=>原因1=>措施,將SQL語句中
-
備註: 參數PROCESSES:
屬性 描述 參數類型 Integer 預設值 40~操作系統依賴數 [10gR2,11gR1]
100[11gR2,12cR1]
該值是派生的,它通常取決於警報日誌中報告的核心數。可修改(不用重啟及時生效) 否 取值範圍 6~操作系統依賴數 基礎參數 是 Oracle實時應用集群 多個實例可以具有不同的值。 PROCESSES指定可以同時連接到Oracle的最大操作系統用戶進程數。它的值應允許所有後臺進程運行,如鎖,作業隊列進程和並行執行進程。
該參數派生了SESSIONS和TRANSACTIONS參數的預設值。因此,如果更改PROCESSES的值,則應評估是否要調整這些派生參數的值。
ORA-01500 to ORA-02098
ORA-01722: 無效數字
ORA-01722: invalid number
原因1: 指定的數字無效
The specified number was invalid.
- 分析: 究其根本在於,要執行的語句在人為顯式轉換或Oracle判斷決定隱式轉換,故意或非故意得使一個非數值類型且無法轉換為數值類型的值轉換為數值類型失敗導致的。如下幾例:
-
顯式轉換:
-- to_number、to_binary_float、to_binary_double轉換字元串為數值 select to_number('2017年') from dual; select to_binary_float('8.935M') from dual; select to_binary_double('0.001s') from dual;
-
隱式轉換:
---------涉及到數值類型列的賦值或函數需要函數數值類型結果的轉換--------- -- insert/update/merge等語句操作列值 -- 測試表 create table ora_01722_1( a number, b char(24), c varchar2(300) ); -- 插入賦值,無法隱式轉換成數值,報錯 insert into ora_01722_1(a) values ('111測試字元串'); -- 插入賦值,可以隱式轉換成數值,不報錯 insert into ora_01722_1(a, b) values ('111', 'bbb'); commit; -- 更新賦值,無法隱式轉換成數值,報錯 update ora_01722_1 set a = '222測試字元串'; -- decode由第三列的數值1確定了改函數輸出結果為數值類型 -- 當匹配到'a'返回1,結果為數值,不報錯 select decode('a', 'a', 1, 'b', 2, 'c', 'three', 0) test1 from dual; -- 當匹配到'c'返回'three',結果不為數值且無法轉換為數值,報錯 select decode('c', 'a', 1, 'b', 2, 'c', 'three', 0) test2 from dual; -- nvl由第一列輸入的數值確定了它在此時輸出的結果也會為數值 -- 當發現第一個值不為空時,就嘗試輸出後邊的值作為本次nvl函數操作後的數值結果,發現無法轉換為數值,報錯 select nvl(&請輸入數值, '測試') from dual; -- nvl2由第二列的2確定了它在此時輸出的結果也會為數值 -- 當不管結果是否為2,它都會講後邊的值進行測試轉換……所以無論是否輸入null都報錯 select nvl2(&無論是否null, 2, '測試') from dual; ---------涉及到與數值類型的比較或其它運算--------- -- 未比較到'三',不報錯 select decode(1, 1, 'one', 2, 'two', '三', 'three', 'zero') from dual; -- 比較到'三',報錯 select decode(3, 1, 'one', 2, 'two', '三', 'three', 'zero') from dual; -- 與數值進行算術運算,無法隱式轉換為數值,報錯 select 'a' + 2 from dual; -- 與ora_01722_1的數值類型列a進行比較,將右邊轉換為數值失敗,報錯 select * from ora_01722_1 t where t.a = 'a'; -- ora_01722_1列b與數值類型進行比較,將左邊轉換為數值失敗,報錯 select * from ora_01722_1 t where t.b = 2;
-
隱式轉換:特別註意時靈時不靈的查詢,都是重新類似於上面的情況,但由於之前查詢的是部分表數據或部分視圖數據等,但是報錯是涉及到另一部分甚至是全表全視圖的數據,而由於未註意隱式轉換導致“臟數據”無法轉換成數值類型而報錯。其實不是它臟,是你不註意欄位類型的區分,請不要依賴於Oracle的隱式轉換!
-
-
措施: 指定一個有效的數字。
Specify a valid number.
- 根據分析的情況,明確是否需要主動轉換,是否數據存在問題,該是數值就傳數值,該是字元串就添加左右英文單引號包裹成字元串。
- 備註: 當需要的時候,Oracle資料庫會自動將值從一種數據類型轉換為另一種(如CHAR、VARCHAR2、NCHAR、NVARCHAR2、BINARY_FLOAT、BINARY_DOUBLE就有可能隱式轉換為NUMBER)。由於以下原因,Oracle建議您指定顯式轉換,而不是依賴於隱式自動轉換:
- 當您使用顯式數據類型轉換函數時,SQL語句更容易理解。
- 隱式數據類型轉換可能會對性能產生負面影響,特別是如果列值的數據類型被隱式轉換為基本常量的數據類型,而不是主動轉為其它類型。
- 隱式轉換要根據需要轉換時的上下文來決定,而且在每類場景中不一定產生一樣的效果。例如,從datetime值到varchar2值的隱式轉換可能會根據NLS_DATE_FORMAT參數的值返回意外的一年。
- 隱式轉換的演算法可能會隨著軟體版本和Oracle產品之間的變化而變化。顯式轉換的變化則更有預見性。
- 如果在索引表達式中產生了隱式數據類型轉換,那麼Oracle資料庫可能不會使用該索引,因為它是為轉換前數據類型定義的。這可能會對性能產生負面影響。
ORA-01747: user.table.column, table.column 或列說明無效【已驗證】
ORA-01747: invalid user.table.column, table.column, or column specification
原因1: 列名為關鍵字。
-
分析: 一般為在SQL語句或存儲過程、函數等中使用到的此欄位為oracle的保留關鍵字,且保留方式標識了此關鍵字在某些情況下,例如在DML中是否不允許作為標識符的。如下列情況:
-- 查詢能做屬性但不能作為標識符或某些場景(如DML操作)下不能作為標識符的關鍵字 select t.* from v$reserved_words t where (t.res_semi = 'Y' or t.reserved = 'Y') and t.res_attr = 'N'; -- 根據上面關鍵字建表,為測試需要,實際使用時請避免將Oracle保留關鍵字作為表的欄位! create table ora_01747_1 ( "TRIGGER" number, "WHERE" number, "REVOKE" number, "INCREMENT" number, "THEN" number, "FILE" number, "PRIOR" number, "CONNECT" number, "COMMENT" number, "SYSDATE" number, "ONLINE" number, "DECIMAL" number, "SESSION" number, "MODIFY" number, "IN" number, "@" number, "," number, "GRANT" number, "INTO" number, "VALIDATE" number, "." number, "ADD" number, "ORDER" number, "HAVING" number, "TO" number, "NULL" number, "RENAME" number, "LEVEL" number, "USER" number, "ANY" number, /*"ROWID" number, --不可作建表屬性*/ "SHARE" number, "MODE" number, "UNION" number, "/" number, "SET" number, "INDEX" number, "MAXEXTENTS" number, "VALUES" number, "|" number, "VIEW" number, "[" number, "WITH" number, "EXCLUSIVE" number, "ALTER" number, "FROM" number, "SELECT" number, "BY" number, "-" number, "MLSLABEL" number, "AND" number, "+" number, "ROWS" number, "CHECK" number, ":" number, "VARCHAR2" number, "IMMEDIATE" number, "CURRENT" number, "AS" number, "*" number, "TABLE" number, "LONG" number, "SYNONYM" number, "ASC" number, "UNIQUE" number, "LIKE" number, "DESC" number, "VARCHAR" number, "INITIAL" number, "CHAR" number, "="