Oracle數據回滾:一次錯誤的事務提交引發的災難

寫下這篇文章的時候,我差點要喫速效救心丸了……

2小時前,我發佈了一次程序更新,有部分歷史數據必須手動在數據庫用SQL進行處理,約幾百條記錄。按照慣例,先在本地開發環境進行測試,然後開始在線上環境測試。真的印證了墨菲定理,幾分鐘後意外發生了……

我執行了錯誤的SQL,還提交了事務!造成的後果就是,有4條髒數據插入了生產環境中有25W行記錄的表中,最要命的是,插入的數據無法根據時間戳排序篩選出來,因爲每秒幾百行的插入和數千次的更新早讓時間標記亂序了。4條數據在25W行中找出來,簡直是大海撈針。

冷靜3秒,我第一件想到的就是查詢SQL執行的歷史記錄。對,歷史記錄可以查到剛纔的SQL!
SELECT SQL_TEXT, LAST_ACTIVE_TIME,SQL_FULLTEXT FROM v$sql ORDER BY LAST_ACTIVE_TIME DESC 執行後,我發現我錯了,我執行的那條錯誤的SQL和線上用戶操作了程序功能後調用的SQL是一個類型的!結果就是,儘管找到了歷史記錄,也不能找到我誤執行的那條!怎麼辦?手動查找?幾十萬條數據,有點不靠譜。

既然Oracle安全性出了名的好,那肯定有很多相關的數據保護機制。那就找找百度、搜狗、Google,網友的力量總是強大的嘛!功夫不負有心人,果然,Oracle是由flashback閃回機制的。通俗點講,就是有個緩存區,會按照時間戳備份每張錶的歷史數據。指定一個時間,就可以查詢到對應時間點之前,這張錶的歷史狀態。
SELECT * FROM tableName AS OF TIMESTAMP TO_TIMESTAMP('20180822 11:00:00','YYYYMMDD HH24:MI:SS');

經過查詢,直接找到了5分鐘前的歷史數據,但有個問題,數據還不夠舊!調整了參數,發現了新的問題——因爲Oracle的相關設置,我最多查到5分鐘的……真是屋漏偏逢連夜雨……

在這裏插入圖片描述
還有什麼辦法?冷靜下來想想,剛纔的操作都是站在開發者的角度,站在用戶的角度呢?對,客戶端程序是有用戶操作歷史記錄的!

通過客戶端歷史記錄,結合時間戳篩查,把範圍從25W縮小到了200條記錄!然後,就沒有然後了,手動找了下,5分鐘,找到了那4條髒數據!

雖然最終沒有利用Oracle的相關機制解決問題,但這次事故還是值得思考的。

覆盤下操作,我發現,真是犯了連幼兒園小朋友都不會犯的錯誤,update條件不是確定的!
update table t set t.enable ='n' where t.enable=‘y’ and t.id in (select t.id from table t where t.enable='y' and t.id2 ='xxx')

update table t set t.enable ='y' where t.enable=‘n’ and t.id in (select t.id from table t where t.enable='n' and t.id2 ='xxx')

我要更新的數百條記錄,沒有用聯合主鍵確定,而是使用了一個狀態位y與n。執行了一次update後,狀態已經發生了改變,再次執行,結果就會完全不一致!

總結下,生產環境操作時,頭腦要清晰,別犯渾。不幹活,養魚呢?說的就是你!

參考:oracle閃回機制簡介,https://www.jb51.net/article/130703.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章