sqlplus註釋導致語句重複執行
意外發現一個sqlplus上一個註釋相關的bug。
看一個簡單的例子:
solaris*orcl-/home/oracle$ sqlplus test/test
SQL*Plus: Release 11.2.0.3.0 Production on Mon Jun 11 17:09:57 2012
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Oracle Label Security and Real Application Testing
options
SQL> set pages 100 lines 140
SQL> select 1 from dual;
這是一個最新的11.2.0.3的sqlplus客戶端,那麼這個簡單的查詢結果是什麼?
SQL> select 1 from dual;
1
----------
1
SQL> /* select */ select 2 from dual;
好,我承認是在故弄玄虛,結果就是簡單到不能再簡單的1,那麼問題來了,上面第二個查詢的結果是什麼?
SQL> /* select */ select 2 from dual;
2
----------
2
SQL> /*select */ select 3 from dual;
不要扔磚,雖然結果還是意料之內的,但是見證奇蹟的時刻馬上就要到了,這第三個查詢的結果是什麼?
SQL> /*select */ select 3 from dual;
2
----------
2
這個結果是不是很2?這個語句和上面第二個語句只是相差了一個空格,結果是完全不同的。對於第二個語句而言,註釋並沒有對語句產生任何的影響;而對於第三個語句,實際上Oracle並沒有把這個語句作為包含註釋的語句看待,實際上sqlplus執行的是/,也就是將快取中的語句再執行一次,而完全忽略了/之後的內容。
可能有些人認為這個bug對於系統的影響不大,而如果在資料庫中執行.sql檔案,或者透過shell呼叫sql指令碼,那麼這個問題出現的可能性就大大增加了。
考慮一下極端的情況,這個問題可能帶來哪些危害。最明顯的莫過於使得上一個執行的SQL重複執行。
SQL> delete t where rownum < 11;
10 rows deleted.
SQL> /*select*/ select count(*) from t;
10 rows deleted.
如果上一條是SELECT,則顯然對系統影響最小(事實上這個影響也不小,因為當前需要執行的SQL被跳過了,這可能影響這個SQL指令碼的邏輯),而如果是DELETE語句,如上所示,那麼表中資料就會被多刪除一次。
也許有人會說,刪除也無所謂,可以進行回滾,並沒有資料的損失。事實上,對於SHELL指令碼方式或者編寫好的SQL指令碼而言,是沒有辦法對其進行控制的。
即使不在指令碼中執行,有些情況下也是沒有機會回滾的,比如:
SQL> create procedure p_sqlplus as
2 begin
3 delete t where rownum < 5;
4 commit;
5 end;
6 /
Procedure created.
SQL> begin p_sqlplus; end;
2 /
PL/SQL procedure successfully completed.
SQL> /*another execute*/ select count(*) from t;
PL/SQL procedure successfully completed.
這種想要恢復就只能透過閃回了。而如果重複執行的是DDL,那麼連閃回的機會都沒有了。
重複DDL的一個例子:
SQL> alter table t_part exchange partition p1
2 with table t_temp_part
3 update indexes;
Table altered.
SQL> /*count the num*/ select count(*) from t_part partition (p1);
Table altered.
SQL> drop table t_temp_part purge;
Table dropped.
雖然並不會真正造成什麼資料的損失,但是資料的載入以及分割槽EXCHANGE的工作就完全白做了。
上面幾個例子都比較極端,但是這是為了說明對於SHELL或SQL檔案中這種自動執行的指令碼,要小心這個bug帶來的不可預料的錯誤。
好在這個問題只是發生在sqlplus中,且SQL語句開頭是以/*方式的註釋開頭,註釋與後面的內容之間沒有空格的情況下,因此想要碰到這個錯誤也並不容易。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-746121/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 執行SQL語句導致mysqld的crashMySql
- 一條執行4秒的sql語句導致的系統問題SQL
- WebMagic多執行緒導致註解失效問題Web執行緒
- MySQL半一致性讀導致語句級Binlog複製錯誤MySql
- mySQL 執行語句執行順序MySql
- 用SQL語句去掉重複的記錄SQL
- for語句執行順序
- sql語句批量執行SQL
- FORALL執行DELETE語句delete
- FORALL執行UPDATE語句
- merge語句導致的ORA錯誤分析
- sqlldr 匯入重複資料導致PK INDEX失效SQLIndex
- 查詢正在執行的sql語句及該語句執行的時間SQL
- 一句話從 MySQL 取出重複行MySql
- sqlplus註釋行號錯誤的問題SQL
- MySQL語句執行分析(一)MySql
- MySQL語句執行分析(二)MySql
- sql語句如何執行的SQL
- SQL語句執行順序SQL
- PHP執行批量mysql語句PHPMySql
- FORALL執行UPDATE語句(二)
- 執行大的sql語句SQL
- toad執行sql語句SQL
- sqlplus註釋問題SQL
- 嚴重 PHP 漏洞導致伺服器遭受遠端程式碼執行PHP伺服器
- Casperjs迴圈執行(重複執行不退出)JS
- 防止指令碼重複執行方法指令碼
- 如何避免任務重複執行
- 查詢Oracle正在執行的sql語句及執行該語句的使用者OracleSQL
- YCSB擴充套件-語句執行頻率,執行指定的測試查詢語句套件
- sqlplus 跟蹤sql語句SQL
- mysql執行sql語句過程MySql
- Mybatis 動態執行SQL語句MyBatisSQL
- mysql的sql語句執行流程MySql
- sql語句執行緩慢分析SQL
- SQL 語句的執行順序SQL
- Select語句執行順序
- 後臺執行SQL語句(oracle)SQLOracle