1. 程式人生 > 其它 >同樣的sql執行結果不同的原因分析 (r4筆記第27天)

同樣的sql執行結果不同的原因分析 (r4筆記第27天)

今天開發的同事問我一個問題,說有一個sql語句,在weblogic的日誌中執行沒有結果,但是手動拷貝資料到客戶端執行,卻能夠查到。這種奇怪的問題一下子就能引起我的好奇心,從我知道的原因來看啊,可能是存在不可見字元造成的。 對於不可見字元的問題,有必要先說明一下,可以簡單舉個例子。 我們建立一個表,然後插入的資料含有不可見字元,比如回車,換行符。 SQL> create table test as select object_id,object_name||chr(10) objname from all_objects where rownum<3; Table created

插入資料之後,我們檢視一下資料。 SQL> select *from test; OBJECT_ID OBJNAME ---------- ------------------------------- 20 ICOL$ 46 I_USER1

簡單的驗證一下,可以看到object_id=46對應的是objname為I_USER1的資料行。

SQL> select *from test where objname='I_USER1'; no rows selected --但是查詢的時候卻沒有任何結果 如果我們在查詢中明確的加入那個不可見字元,就可以很容易就插敘出來。

SQL> select *from test where objname='I_USER1'||chr(10); OBJECT_ID OBJNAME ---------- ------------------------------- 46 I_USER1

這個時候可以使用dump函式來分析。 如果可以對比一下資料的dump細節,可以發現唯一的差比是最後有一個chr(10)的字元

SQL> select object_id,dump('I_USER1') DUMP1,dump(objname) DUMP2 from test where objname like 'I_USER%';

OBJECT_ID DUMP1 DUMP2 ---------- ---------------------------------- -------------------------------------------------- 46 Typ=96 Len=7: 73,95,85,83,69,82,49 Typ=1 Len=8: 73,95,85,83,69,82,49,10

但是當我自信滿滿的查看了開發提供的日誌之後,然後在客戶端中又執行了一遍,發現問題似乎比預想的更有些奇怪。 語句是一個簡單的select語句,類似select xxxx,xxxxx,xxxx from districute where entity_id=:id and status='ACTIVE', 其中entity_id是傳入的引數。 在反覆比較之後,基本上這個地方不太可能出現問題,在API想傳入這個特殊字元都不容易。但是一模一樣的語句在兩邊執行結果卻不相同。 肯定是某個地方出了問題,我靜下來,仔細的分析日誌中的sql語句,按照目前的情況來說,只可能在某處修改了資料導致的,從這個查詢語句往前排查,最終發現了線索。 在這個查詢之前,其中有一步是update操作,語句類似update distribute set xxxx=xxx where distribute_no=:distid 從表面上來看,兩個語句的唯一共同之處在於都是基於同一個表。 檢視sql語句中對應的變數值,發現在select之前的這步操作已經修改了對應的status值,所以在後續的查詢中根據entity_id就匹配不到相應的記錄了。 通過資料來說明,就如同下面的情況,我們通過distribute_no修改了status值,再通過status,entity_id來匹配對應的資料行得到的結果就為空,在得到的結果為空後,校驗失敗,於是事務就回退了。然後下一次呼叫繼續update,select,rollack。 entity_id status distribute_no xxxx 100 ACTIVE 100001 xxxxx 分析了這些之後,問題就一下子明朗多了,不是什麼特別的bug,不是什麼特別的場景,都是潛意識中自己被誤導了。所以大家在排查問題的時候,可能提供給你的資訊不是最全面最完整的,我們需要分析去佐證。