ORA-01555是一個很經典很常見的錯誤.產生的原因是你的查詢sql在構造CR的時候,發現undo中的CR塊被覆蓋了,就會產生ORA-01555.
一般的解決思路:
1.優化sql
2.加大undo表空間
3.加大undo_retention,加大undo的保留時間
但是我這次遇到的確不是上面的情況.
首先現象是,一個簡單的查詢,報錯ORA-01555,快照過舊:
Select * From 住院費用記錄 t Where t.病人id=1023738;
這個sql語句非常簡單,病人ID上面也有索引,但是一執行就會報錯ORA-01555.查詢alert日誌,如下:
Fri Oct 11 11:34:28 2019
ORA-01555 caused by SQL statement below (SQL ID: gmwgdkyndx34j, Query Duration=0 sec, SCN: 0x0001.95ad6c0e):
Select * From 住院費用記錄 Where 病人id = 1023733
Fri Oct 11 11:34:31 2019
ORA-00060: Deadlock detected. More info in file D:\APP\ADMINISTRATOR\diag\rdbms\orcl\orcl\trace\orcl_ora_9744.trc.
ORA-01555 caused by SQL statement below (SQL ID: gmwgdkyndx34j, Query Duration=0 sec, SCN: 0x0001.95ad6c99):
Select * From 住院費用記錄 Where 病人id = 1023733
Fri Oct 11 11:34:46 2019
這裏的執行時間爲0 sec.這裏明顯感覺不是因爲構造CR塊的時候undo被覆蓋導致的.懷疑可能是bug.於是搜索MOS,發現一篇文件正好一致:
IF: ORA-1555 Reported with Query Duration = 0 , or a Few Seconds (文檔 ID 1950577.1)
APPLIES TO:Oracle Database Cloud Service - Version N/A and later
Oracle Database - Standard Edition - Version 11.2.0.1 to 11.2.0.1 [Release 11.2]
Oracle Database Cloud Schema Service - Version N/A and later
Oracle Database Exadata Cloud Machine - Version N/A and later
Oracle Cloud Infrastructure - Database Service - Version N/A and later
Information in this document applies to any platform.SYMPTOMS
a) An incorrect ORA-01555 error is reported with Query Duration=0
e.g
Error message in the alert Log / console will look similar to this:
Wed Jan 4 11:11:56 2014
ORA-01555 caused by SQL statement below (SQL ID: 1dnh4ypr7734w, Query Duration=0 sec, SCN: 0x0000.00be7c41):OR
b) ORA-1555 with (extermely) small query duration reported in the error message. Eg:ORA-01555 caused by SQL statement below (Query Duration=9 sec, SCN: 0x0001.8be5c8d1):
CAUSE
ORA-1555 with Query Duration 0 or a few seconds is mainly caused by indexes/table mismatch Or primary key index corruption.
Similar error is reported for flashback queries or queries involving dblinks.
這裏提到了,原因是索引/表不一致,或者主鍵索引壞塊.
結合現實環境,上面的sql語句走病人ID這個索引,於是嘗試做一個全表掃描的查詢,看是否報錯:
Select /*+ FULL(t) */ * From 住院費用記錄 t Where t.病人id=1023738;
發現正常.說明表是正常的,但是當通過索引訪問數據的時候出現報錯,那麼定位應該是這個索引有邏輯壞塊.
那麼解決辦法就很簡單了,只要重建索引就可以了.由於這個表很大,使用了在線併發重建索引:
alter index XXX rebuild online parallel 8;
別忘了關閉索引的併發度:
alter index XXX noparallel;