您好,登錄后才能下訂單哦!
作者 | 鄭松林
轉自 | 數據和云
微信號 | OraNews
分析一次SQL并行執行的產生過程
1、并行引起的災禍
一大早,某網省兄弟告訴我,數據庫會話執行的SQL開啟了并行,導致負載很高,會話也高,查了半天,沒找到具體原因,也不知道該如何解決?
對于他的問題,我直接回應了:這還不清楚嗎?常見原因無非有以下兩個:
第一:對象開啟了并行(包括索引和表)
第二:SQL語句里面使用了PARALLEL的HINTS
現場兄弟說,都查了并沒有上面的情況,聽到他的回答,我首先對他查詢的方式持懷疑態度的,沒有設置并行度,也沒有加HINTS,執行的SQL怎么會并行執行呢?帶著這個疑問,我叫現場兄弟把查詢結果一一截圖給我,如下(文中案例都是事后補充):
看到結果后我一時也有點摸不著頭腦,怎么回事?遇到問題我總是告訴自己要冷靜,不急。
2、層層推進,分析問題
是不是什么參數控制了?
SQL> show parameter parallel
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
fast_start_parallel_rollback string LOW
parallel_adaptive_multi_user boolean TRUE
parallel_automatic_tuning boolean FALSE
parallel_degree_limit string CPU
parallel_degree_policy string MANUAL
parallel_execution_message_size integer 16384
parallel_force_local boolean FALSE
parallel_instance_group string
parallel_io_cap_enabled boolean FALSE
parallel_max_servers integer 320
parallel_min_percent integer 0
parallel_min_servers integer 0
parallel_min_time_threshold string AUTO
parallel_server boolean FALSE
parallel_server_instances integer 1
parallel_servers_target integer 128
parallel_threads_per_cpu integer 2
recovery_parallelism integer 0
沒有發現可疑參數。
至此,表面排查的結果已經解決不了這個問題了,于是我讓現場找了一條正在并行的SQL ,手動執行,并收集一個10053事件trace,看看是否能有新發現。腳本如下
很快現場提供了TRACE FILE文件給我,我優先看參數列表。
這時,我發現一個可疑的參數:parallel_query_default_dop = 16
找到mos上關于該參數的相關信息,是一個默認并行度的參數,該參數值的算法如下:
DEFAULT DOP = cpu_count * parallel_threads_per_cpu* cluster_database_instances
我立刻問現場同事,執行的SQL在活動會話中體現的是不是16個并行進程。現場同事答復我,觀察到的基本就是。至此問題明朗起來了,執行的SQL使用了默認并行度執行,受參數parallel_query_default_dop控制。既然是默認的并行度,那也應該需要設置(如果不設置,默認是1)。于是我把前期的查詢驗證對象并行度是否開啟的SQL改造了下,具體如下(文中案例都是事后補充)
查詢結果截圖發出來,我就開心了,這里明顯有一個設置了并行度為DEFAULT(如果我們不設置就是1)的表和索引。然后確認了他們正是正在運行的sql中的對象。
3、問題解決
既然設置了默認并行度,那么只需要取消默認并行度即可,即執行如下SQL
--針對表
alter table table_name noparalle;
--針對索引
Alter index index_name noparallel;
于是我叫現場把對象并行度修改為1,再次執行該SQL,發現并行消失了,數據庫恢復了正常。
問題雖然解決了,但還有一個疑問沒有解開,什么情況下會設置的并行度為DEFUALT呢?正常創建索引和表都是1。
4、如何設置并行度為default
通過實踐發現如下2種方式可以實現并行度設置為DEFAULT。
1、創建表的時候指定:
2、創建表之后可以修改
小結:該問題解決第一個是思路 ,第二個是基本功要扎實。
1
DB升級之后,DBLINK引起執行計劃異常分析
背景如下:某網省采集中間庫從10.2.0.4升級到11.2.0.4(備注升級不是在老的機器上面直接升級,而是在新機器上面采用安裝遷移的方式)
升級完第二天現場找到我,說以前同步檔案數據的接口功能目前都運行非常慢(數據接口同步的方式采用的DBLINK),有時甚至無法正常運行完,影響檔案資料的同步,看來已經很嚴重了。
關鍵字:DB升級從10G升級到11G
我以前遇到過相關案例,覺得可能是升級帶來的執行計劃變化引起的。于是告知現場嘗試修改優化器參數即optimizer_features_enable改成10.2.0.4,可以在線改,立刻生效,腳本如下:
alter system set optimizer_features_enable='10.2.0.4' scope=both;
修改完成后,重新在執行同步檔案資料接口的任務看是否正常。
現場經過一番測試之后,問題沒有解決,看來老的經驗無法解決該問題。
好,接下來我們做了以下模擬測試:
該SQL的文本如下:
INSERT INTO EPCT.C_CUST_ADDR@EPEXDB
(CUST_ID,
CUST_ADDR,
PROVINCE_CODE,
CITY_CODE,
COUNTY_CODE,
STREET_CODE,
VILLAGE_CODE,
ROAD_CODE,
COMMUNITY_CODE,
PLATE_NO,
TYPE_CODE,
POSTALCODE,
CA_ID,
APP_NO)
SELECT A2.CUST_ID,
A2.CUST_ADDR,
A2.PROVINCE_CODE,
A2.CITY_CODE,
A2.COUNTY_CODE,
A2.STREET_CODE,
A2.VILLAGE_CODE,
A2.ROAD_CODE,
A2.COMMUNITY_CODE,
A2.PLATE_NO,
A2.TYPE_CODE,
A2.POSTALCODE,
A2.CA_ID,
''
FROM SGPM.C_CUST_ADDR A2
WHERE A2.CUST_ID=ANY
(SELECTA3.CUST_ID
FROM SGPM.C_CONS A5,
SGPM.R_CP_CONS_RELA A4,
SGPM.C_CUST A3
WHERE A4.CONS_ID=A5.CONS_ID
AND A4.CP_NO=:B1
ANDA5.CUST_ID=A3.CUST_ID);
可以看到是用到DBLINK從A數據庫到B數據庫的插入語句,這個SQL發起端在A數據庫,也就是程序部署在A數據庫中,而該SQL實際執行端在B數據庫。雖然是往B數據庫插入數據,但是會派生一個查詢SQL到A數據庫取數。
針對INSERT INTO remote_table@dblink select * from local_table這種SQL執行端都會在遠端,不是本地,無法使用HINTS driving_site指定執行端。
2、然后會在A數據庫確認一下是否派生一個SQL,并且找到該SQLID
3、現場提供SQLID之后,我們可以獲取該sql執行的相關信息:
select *from table(dbms_xplan.display_cursor('1ar4us01aj0hu',null,'ADVANCED'));
紅框里出現的字樣引起了我的注意,眼尖的DBA應該很快會發現其中的貓膩。
對的,這里調用了一個內部函數。這個函數的說明如下:
The internal Oracle function SYS_OP_C2C performs conversion
from one character set to another character set C(haracterSet)2C(haracterSet).
字符集之間的轉換。OK ,看到這里我問現場,新舊兩套B數據庫中字符集是什么? A數據庫字符集又是什么?
現場答復如下:
老的B數據庫字符集是utf-8
新的B數據庫字符集是zhs16gbk
而A數據庫字符集是utf-8
這個也就說明了,遷移到新采集中間庫之后性能急劇下降的原因找到了。
那么解決方式有如下2種方式:
第一修改字符集,保證源目標字符集一致。
第二創建函數索引。
2
域索引導致提交報告的展開討論
域索引導致提交報錯
最近處理了一個網省的問題,現場反饋提交報錯 ,報錯如下:
COMMIT;
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20000: Oracle Text error:
DRG-50610: internal error: drexdsync
DRG-50857: oracle error in drekrtd (reselect rowid row locator)
ORA-00942: table or view does not exist
ORA-06512: at "CTXSYS.SYNCRN", line 1
ORA-06512: at line 1
看到這個錯誤,我們獲取到如下信息
1、這個是關于域索引的報錯
2、這個是遞歸SQL導致的報錯
3、這個是報表或者視圖不存在(最大可能是權限 或者可能就是真不存在)
見到這個錯誤,首先找現場核實下權限問題,包括操作用戶的權限
核查結果并沒有異常。
進一步分析:
1、查詢域索引信息
Select * from ctxsys.ctx_indexes
2、創建一個域索引會自動創建屬性為BASIC_STORAGE的四個二級表對象和一個索引對象出來
BASIC_STORAGE has the following attributes:
i_table_clause Parameter clause for dr$<indexname>$I table creation.
The I table is the index data table.
k_table_clause Parameter clause for dr$<indexname>$K table creation.
The K table is the keymap table.
r_table_clause Parameter clause for dr$<indexname>$R table creation.
The R table is the rowid table.
n_table_clause Parameter clause for dr$<indexname>$N table creation.
The N table is the negative list table.
i_index_clause Parameter clause for dr$<indexname>$X index creation.
大家可以在自己的環境中使用如下SQL查詢
Select owner,object_name,object_type,secondary,status
from dba_objects
where owner ='SGPM'
and object_name like 'DR$INDEX_NAME$%' --INDEX_NAME修改為你實際的名稱
現場查詢結果為空,說明域索引已經不存在了,從而導致提交報錯,也就是遞歸執行域索引的SQL報錯。
問題定位到,解決問題的辦法很容易:
重建域索引即可。
我這里給出的例子指出了域索引的實際存儲表空間位置,目的就是可控,如果不指定就是創建用戶所在默認的表空間。
begin
--創建詞法分析
--ctx_ddl.create_preference ('chinese_lexer', 'chinese_lexer');
--存儲參數
ctx_ddl.create_preference('t1_stor','BASIC_STORAGE');
ctx_ddl.set_attribute('t1_stor','I_TABLE_CLAUSE','tablespace TEST');
ctx_ddl.set_attribute('t1_stor','I_INDEX_CLAUSE','tablespace TEST');
ctx_ddl.set_attribute('t1_stor','K_TABLE_CLAUSE','tablespace TEST');
ctx_ddl.set_attribute('t1_stor','R_TABLE_CLAUSE','tablespace TEST');
ctx_ddl.set_attribute('t1_stor','N_TABLE_CLAUSE','tablespace TEST');
end;
--創建域索引 指定storage參數和lexer詞法分析器參數
create index idx1_t1 on t1(object_name) indextype is ctxsys.context parameters ('lexer chinese_lexer storage t1_stor');
--同步域索引數據:(該操作有風險業務低估操作)
查詢確認域索引是否需要同步
select u.username, i.idx_name
from ctxsys.dr$index i, dba_users u
where u.user_id=i.idx_owner#
and idx_id in (select pnd_cid from ctxsys.dr$pending);
exec ctx_ddl.sync_index('IDX1_T1');
--優化域索引數據(該操作有風險業務低估操作)
exec ctx_ddl.optimize_index ('IDX1_T1', 'full');
3
作者簡介
鄭林松,朗新科技股份有限公司數據庫技術專家,從業10多年,主要服務移動運營商客戶,電力客戶,證券客戶,制造業客戶。精通 Oracle 性能優化,故障診斷和處理,也擅長MySQL數據庫優化和故障處理。主要負責朗新公司國家電網12個網省性能優化和故障處理工作以及南方電網性能優化和故障處理工作,主導過某證券公司冷熱數據隔離和空間回收工作(總數據量100T),主持過某電網公司XTTS遷移工作;電網公司核心營銷系統歷史數據空間回收和高水位處理工作,合計回收空間15T。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。