天天看點

18C 也不能避免 SQL 解析的 Bug

概述

在 Oracle 12.2 版本和新釋出的18.0版本中存在一個 SQL 解析的 bug,導緻了資料庫背景報 ora-07445 或者 ora-00600 錯誤。報 ora-07445 時,可導緻資料庫斷開目前會話連接配接,無法進行 SQL 操作,當報 ora-00600 時,會話沒有斷開,但無法完成解析傳回結果。

該 bug 的發現敬請參考:http://www.hellodba.com/reader.php?ID=221&lang=CN

觸發 Bug 的現象

背景 alert 日志:

18C 也不能避免 SQL 解析的 Bug

Sqlplus 顯示:

18C 也不能避免 SQL 解析的 Bug
18C 也不能避免 SQL 解析的 Bug

該報錯,是在測試重制 ora-07445 時發現的。以下我們一起來重制一下 ora-7445 的報錯。

Bug 重制測試

讀者可以按照以下的語句,可以在 Oracle 12.2 和18.0的版本中測試,重制這個 SQL 解析的 bug,觀察報錯情況。重制這個 bug 重點符合以下條件:

表中有一個運作為空的字段;

該字段的統計資訊被收集過;

該字段中存在空值和非空值。

18C 也不能避免 SQL 解析的 Bug
18C 也不能避免 SQL 解析的 Bug
18C 也不能避免 SQL 解析的 Bug

讀者可以按照這個測試過程,在自己的測試環境重制 ora-07445 報錯,記住,決不能在生産環境的 12.2 的庫上測試。

報錯的資訊追蹤和影響

通過伺服器上看這個 ora-07445 為核心存儲内部的錯誤。

18C 也不能避免 SQL 解析的 Bug

1> show incident 檢視報錯資訊摘要:

18C 也不能避免 SQL 解析的 Bug

2> 檢視比較接近的一個 incident_id 的摘要詳情:

18C 也不能避免 SQL 解析的 Bug
18C 也不能避免 SQL 解析的 Bug

Oracle 12.1中基于成本模式的 SQL 執行計劃:

18C 也不能避免 SQL 解析的 Bug

通過 Oracle 官網文檔 ORA-600/ORA-7445/ORA-700 Error Look-up Tool (Doc ID 153788.1)檢視報錯号對應的 bug 資訊,發現官網未對 oracle 12.2 或者 18.0 這個 SQL 解析的 bug 作釋出,如下:

18C 也不能避免 SQL 解析的 Bug

由于這個 ora-07445 報錯出現在之前的多個版本的不同場景,以下為12.1版本中有類似的 bug 可以參考一下:

18C 也不能避免 SQL 解析的 Bug

以及官網文檔:

兩篇文章中分别提到了:查詢當中循環多次使用到某個對象,以及空值參與到了部分連判斷運算。

這個 SQL 解析的 bug 的影響可以從兩方面來看。

經過多次的測試實驗的觀察,在解析語句到會話中斷這個過程,消耗比較多的 CPU 資源和記憶體資源,如果在比較繁忙的生成系統,有可能導緻資料庫被 hang 住,影響生産。

避開解析 Bug 的方法

根據上述的條件,經過另外的測試資料,使用變量控制法,模拟了一系列的測試實驗得出觸發該解析 bug 同時滿足以下條件:

為 with 子句形式;

where 子句中字段的統計資訊被收集過;

資料庫表 D 的字段可以不存在空值,但在臨時表 A 從表 D 擷取資料的 where 字句中存在關于 null 判斷運算。則上述中分别為:decode(d1,null,val1,val2[,...]),nvl(expr1,expr2)或者nvl2(expr1,expr2,expr3);

decode、nvl 或者 nvl2 内嵌套有 Oracle 資料庫内部函數,如to_number,round,trunc 等;

With 子句結構中,臨時表 B 和臨時表 C 都經臨時表A産生;

臨時表 B 和臨時表 C 中有至少有一個臨時表 A 和僞表 dual 構成笛卡爾連接配接查詢,并且通過 distinct 去重;

最終的結果通過臨時表 B 和臨時表 C 做連接配接查詢而得。

18C 也不能避免 SQL 解析的 Bug

例1:上述條件6,将僞表 dual 和 distinct 分别放在兩個臨時表中:

18C 也不能避免 SQL 解析的 Bug

例2:上述條件4,nvl() 函數内不嵌套 Oracle 内部函數,直接使用标量 5100

18C 也不能避免 SQL 解析的 Bug

在目前測試版本的資料庫,優化器預設是使用基于成本的模式,而使用基于規則的模式可以避開該解析 bug,成功解析語句。

預設優化模式參數:

18C 也不能避免 SQL 解析的 Bug

調整該優化參數為 rule:

18C 也不能避免 SQL 解析的 Bug

解析一語句已成功解析:

18C 也不能避免 SQL 解析的 Bug

解析二語句已成功解析:

18C 也不能避免 SQL 解析的 Bug

這裡跟上述,同樣的語句,但看不到報 ora-00600 的錯。

目前會話的優化模式為 ALL_ROWS,同樣使用以上兩個語句進行測試驗證。

解析一:

18C 也不能避免 SQL 解析的 Bug

解析二:

18C 也不能避免 SQL 解析的 Bug

以上兩個語句使用了 hint 訓示之後,原來不能正常解析的,沒有觸發正常解析,其實原理和方法二是類似的。

總結

以上展示部分的測試實驗情況,沒有完全展現出來。本次的測試使用了變量控制法,逐個因素地測試,嘗試找出觸發 Oracle 12.2 SQL 解析 bug 的條件。個人技術知識方面有限,難免還存在一些不足,希望得到更多一些的指點。雖然目前未能很準确定位該 bug,目前我們能夠确定的就是以上幾個條件,能觸發這個解析的 bug,相信在日常生産的業務應用中,是很難遇到這個 bug 的。就算你很幸運在維護資料庫中遇到 SQL 解析的 bug,不妨可以嘗試按照以上介紹的三種方法,去繞開這個 bug。可以是在 session 級别設定 optimizer_mode 參數值為 RULE,也可以是加上 RULE 訓示,最終這兩個的作用是一樣的。

原文釋出時間為:2018-03-6

本文作者:蘇星開