誤刪一張80億數(shù)據(jù)表的索引是怎樣的體驗

當然是嚇瘸了

Friday目前就職于一家外企IT公司,總部是在美國,F(xiàn)riday在中國。得益于時差的關(guān)系,東西兩邊的工作能進行24小時相對無縫的切換協(xié)作。Friday每天的日常就是早上到公司,先回復下對面美國同事的相關(guān)郵件,然后開始一天的開發(fā)任務(wù),下班前將當天的進度和問題發(fā)回總部確認,如果有必要的話,下班后等美國的同事上班發(fā)起一輪電話會議。

今天,本又是個平平無奇的一天,F(xiàn)riday來到公司開始一天的日常。打開郵件,美國同事要求Friday幫忙刪除一張表的某條索引,因為在此時中國的時間是業(yè)務(wù)每天的低峰時刻,幾乎沒有什么流量?!俺R?guī)操作”,F(xiàn)riday心道。很快他便寫好了刪除的命令,打開sqldeveloper進行了一波操作,“唔...為什么刪了這么久”,索引刪除了,但是Friday感覺有點不對,這本是一張不大的表,理論上秒秒鐘就可以操作完成了,仔細一看后,F(xiàn)riday心涼了半截 -- 他刪錯索引了!再仔細檢查后,他意識到自己麻煩大了-- 這個誤刪的索引的表有近80億條數(shù)據(jù)(難怪刪除花了不少時間,按照一般的方式,重建肯定要花很久的時間。好在此時是業(yè)務(wù)低谷,否則肯定各種瘋狂告警和被投訴了。

Friday決定先死馬當活馬醫(yī),立刻進行索引重建,但是情況并不樂觀。通常情況下對oracle的表建立索引的時候并不需要考慮效率問題,這個通常情況指的是相應(yīng)的表數(shù)據(jù)在百萬級以下。一旦數(shù)據(jù)量大到千萬級,億級甚至更大的時候,就不能不考慮新建索引的效率問題,因為當表在建立索引的時候,會產(chǎn)生鎖阻塞新數(shù)據(jù)的更新,如果索引不能很快地建立完畢,會對生產(chǎn)環(huán)境造成影響。而Friday現(xiàn)在面臨的問題是,重建的速度太慢以致于從進度上看預計需要幾十個小時才能完成,而再過8個小時就是美國那邊的上班時間,業(yè)務(wù)的流量高峰也會相應(yīng)到來,想到這里Friday感覺自己有點窒息了?!耙欢ㄓ修k法的”,F(xiàn)riday定了定神開始想對策。

“1. 正在執(zhí)行的重建索引繼續(xù)讓它執(zhí)行,如果所有辦法失效,這就是最后的保障?!?br> “2. 調(diào)查一下索引刪除的影響范圍,應(yīng)該不至于整個系統(tǒng)不可用。” Friday迅速過了一下代碼,果然這張表只在一個統(tǒng)計類的功能里用到了,不屬于核心功能范圍,即使暫時一段時間不可用應(yīng)該也影響不大。(真的嗎? 下文分析)
“3. 馬上找優(yōu)化重建索引效率的辦法,爭取在4小時內(nèi)重建完成”
“4. 要不要報告下領(lǐng)導...算了先瞞著...不行了再說” (呵呵...)

計算機的世界是一套嚴密的邏輯體系,凡事都是有跡可循,因果關(guān)系貫穿始終。一旦掌握原理,就可以扮演上帝進行法則的干預。想要優(yōu)化建索引的效率,首先看創(chuàng)建索引到底做了些什么操作。

  1. 把索引key的數(shù)據(jù)讀到內(nèi)存

如果數(shù)據(jù)沒在db_cache 中,這時候很容易有大量的db file scatter read wait

  1. 對索引key的數(shù)據(jù)作排序

sort_area_size 或者pga_aggregate_target 不夠大的情況下,需要做 disk sort, 會有大量的driect path read/write , 另外,消耗大量CPU Time

  1. 創(chuàng)建新的index segment ,把排過序的索引數(shù)據(jù)寫到所創(chuàng)建的index segment 里面.

如果index 很大,有時會有redo log 相關(guān)等待

那么,只要對這幾個方向進行相應(yīng)的優(yōu)化,就有可能加速整體的效率。經(jīng)過一番研究,F(xiàn)riday得出結(jié)論: 增大pga,增大temp tablepace, 并且用nologging或并行選項。

救火方案有了,看著依舊在龜速重建的進度,F(xiàn)riday決定直接用新的方案進行嘗試,畢竟不會更差了,而且也沒有環(huán)境和時間進行模擬。還好這次幸運女神站在了Friday這邊,優(yōu)化后只用了20分鐘就將索引重建完畢,一切又回到了正軌。

Friday這一天過得驚心動魄,他事后進行復盤覺得自己實在是犯了一個非常低級的錯誤,以致于差點就長跪不起,今后一定要仔細檢查,避免再犯。

然而我們更深入地進行思考,事情其實并沒有這么簡單。

  1. Friday 作為一個開發(fā)人員,為何對數(shù)據(jù)庫有如此高的權(quán)限,以至于DBA都沒有什么存在感

  2. 一個“危險”的DDL操作完全沒有被審核的操作,DML那就更不用說了。

  3. 故障發(fā)生后,F(xiàn)riday并沒有第一時間上報,而是主觀憑自己的經(jīng)驗進行了評估,并企圖自己修復掩蓋失誤,雖然最后的結(jié)果是成功了,但并不足取。原因有幾:

    • 由于經(jīng)驗、技術(shù)能力和視野所限,開發(fā)并不一定能正確評估風險。比如:Friday認為這個故障只是影響了部分小眾功能,問題不大,但是實際上,只要有足夠的流量,沒有索引的慢查詢是足以拖死整個系統(tǒng)的,因為慢查詢會占用數(shù)據(jù)庫的連接,不能及時釋放,當連接數(shù)用完后,其他正常的功能就無法連接數(shù)據(jù)庫,導致整體不可用。其二,F(xiàn)riday的視野只是局限在自己的代碼上,也許上報leader后他會發(fā)現(xiàn),這個表還被其他工程甚至其他團隊共用,而這其中的風險并沒有評估到
    • 能獨立解決問題是能力強的表現(xiàn),但是面對線上故障,群策群力更有助于問題的解決。如果有專業(yè)DBA的幫助,可能會更快,更低風險地解決故障。而如果因為對自己能力的估計過于樂觀進行冒失操作,可能會引起更大的風險和故障。

故障的發(fā)生有時候不是一人或是一事的得失,這是一個系統(tǒng)性的問題。一個良好的系統(tǒng)應(yīng)該是可以規(guī)避風險,甚至自愈的。Friday 可能是個救火能手,但是對于系統(tǒng)上層建筑的機制完善此刻還沒有足夠的意識。


附 oracle大表加速索引建立的實操手冊

1. PGA設(shè)置

hash_area_size: 這個參數(shù)控制每個會話的hash內(nèi)存空間有多大。它也可以在會話級和實例級被修改。默認值是sort area空間大小的兩倍 sort_area_size: 因為排序通常是在PGA中進行的,需要防止因空間或內(nèi)存不足導致需要disk排序。

alter session set workarea_size_policy=manual;
alter session set hash_area_size=100000;
alter session set sort_area_size=2000000000; -- 在系統(tǒng)可用內(nèi)存足夠的情況下,最大可以到2G

question

  1. 什么是PGA
  2. 什么是SGA

2. 增加temp表空間

因為大表的數(shù)據(jù)量比較大,導致建索引時需要的temp表空間也比較大,一般來說接近索引的大小,沒把握的情況下可以估算一下索引的大小先:

另外在建索引的過程中也可以隨時監(jiān)控表空間的使用情況,一旦發(fā)現(xiàn)temp表空間不夠,可以隨時加大

set serveroutput on
declare  
 v_ddl varchar(1024);  
 v_used_bytes number;  
 v_alloc_bytes number;  
 begin  
 dbms_space.create_index_cost(  
 ddl =>' create index ids_t on user(userid)',used_bytes=>v_used_bytes,alloc_bytes =>v_alloc_bytes);  
 dbms_output.put_line('used_bytes='||v_used_bytes||' bytes'||' alloc_bytes='|| v_alloc_bytes || ' bytes');  
 end;
 /

3. 使用并行參數(shù)

關(guān)于利用并行度創(chuàng)建索引,前提是多個CPU,單CPU下用并行度創(chuàng)建索引,可能會造成資源的爭用。理論上來說8個CPU, 可以用parallel 6 ,最多占用6個CPU,另外留下兩個CPU供其他進程使用。 查看CPU核數(shù)的方法有很多, 最簡單地就是用下面這個sql直接查

SELECT * FROM v$osstat where stat_name='NUM_CPUS';

4. 使用nologging

nologging, 絕對應(yīng)該使用,能減少大量redo log,使速度大幅上升。

于是一個比較標準的并行nologging建索引語句就出爐了。對于生產(chǎn)環(huán)境,保險的辦法是再加上online參數(shù),避免建索引時的鎖對dml產(chǎn)生阻塞。

CREATE INDEX  table_idx ON table (col )  NOLOGGING PARALLEL 6;

Note

對于一個比較大的操作,oracle可能會有等待事件發(fā)生 首先可以通過sql developer查看等待時間的信息,得到等待時間的p1,p2,p3。然后通過下面的sql轉(zhuǎn)換p1,p2得到具體等待的object。

select owner,segment_name,segment_typefrom dba_extentswhere file_id = &P1 and &P2 between block_id and block_id + blocks -1;

監(jiān)控oracle 大事務(wù)的執(zhí)行進度

set linesize 400;
set pagesize 400;
set long 4000;
col sql_fulltext format a100;
col opname format a15;
SELECT se.sid,
         opname,
         TRUNC (sofar / totalwork * 100, 2) pct_work,
         elapsed_seconds elapsed,
         ROUND (elapsed_seconds * (totalwork - sofar) / sofar) remain_time,
         sql_fulltext
    FROM v$session_longops sl, v$sqlarea sa, v$session se
   WHERE sl.sql_hash_value = sa.hash_value
         AND sl.sid = se.sid
         AND sofar != totalwork
ORDER BY start_time;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應(yīng)的列上鍵入重復值時,會觸發(fā)此異常。 O...
    我想起個好名字閱讀 5,973評論 0 9
  • 特別說明: 1、本文只是面對數(shù)據(jù)庫應(yīng)用開發(fā)的程序員,不適合專業(yè)DBA,DBA在數(shù)據(jù)庫性能優(yōu)化方面需要了解更多的知識...
    安易學車閱讀 2,150評論 0 40
  • 常用語句: sql/plus sqlplus 'amdocs/Amdocs.Jx.China.110#@ysdb1...
    好好學習的蝸牛閱讀 3,408評論 0 0
  • 索引 數(shù)據(jù)庫中的查詢操作非常普遍,索引就是提升查找速度的一種手段 索引的類型 從數(shù)據(jù)結(jié)構(gòu)角度分 1.B+索引:傳統(tǒng)...
    一凡呀閱讀 3,217評論 0 8
  • 轉(zhuǎn)載自:https://www.cnblogs.com/easypass/archive/2010/12/08/1...
    SkTj閱讀 624評論 0 1

友情鏈接更多精彩內(nèi)容