#!/usr/bin/ksh #set -x column_name_long=48 A_USERNAME=a15 USR_NOT_NULL=" and s.username != 'NULL'" HOSTNAME=`uname -n` ACTION=DEFAULT ROWNUM=30000 function help { cat <] # List summary stats. Optionaly order by [] p : hard parse c : sort by CPU r : physical read b : block change g : gets cc : consistent change sl -r # session actually running an sql sl -i # program column length is set to | sl -m # display machine name instead of last activity sl -b # limit selection to session owned by | sl -o # list under a short form sl -siz # show session memory size | sl -lw # active session locking and waits (10g) sl -c # show cpu and db time | sl -ash [nn] # show waits from active session history. sl -t # show events impact breakdown on session | # default is last 60 minutes sl -e # show session stats, waits and events | sl -f # Failed over sessions sl -io # Show session IO | sl -cpu # Report Response time breakdown sl -sup # Suspend a session (freeze) s=suspend r=resume # Example : sl sup 45 s -->suspend session 45 # sl sup 45 r -->resume session 45 Dumps: sl -dump [ -pga |-pga_adr | -st ] # Dump session PGA stack, protion of PGA (adr) or Session process state sl -rf -pga # read dump of pga Additionals: -rac # target GV\$ instead of V\$ -len # len of the column program -u # Limit Selection to user Example : sl -l r -rn 20 # list all session order by disk reads, limits to 20 first rows ----------------------- Snapper implementation: ----------------------- sl -p -s -n -g [t|s|l|w|e] -ulike -plike -g # option on snaper, can be cumulated : s - Session Statistics from v$sesstat t - Session Time model info from v$sess_time_model w - Session Wait statistics from v$session_event and v$session_wait l - instance Latch get statistics ( gets + immediate_gets ) e - instance Enqueue lock get statistics sl -p 155 -s 1 -g t -g w EOF exit } FIELD7="s.last_call_et ssa" FIELD4="s.serial#," typeset -u FTYPE SEP= while [ -n "$1" ] do case $1 in -a ) ACTION=ASH; if [ -z "$2" ];then MIN=60 else MIN=$2; shift fi ;; -b ) unset USR_NOT_NULL ; A_USERNAME=a25 ; column_name_long=32;; -c ) ACTION="DB_CPU" ;; -f ) ACTION="SLF" ;; -io ) ACTION="SLIO"; SID=$2 ; shift ;; -cpu ) ACTION=CPU ;; -dump ) ACTION=DUMP ; SID=$2 ; shift ;; -st ) DUMP_VAR=ST ;; -pga ) DUMP_VAR=PGA ;; -pga_adr ) DUMP_VAR=PGA_ADR ; START_ADR=$2 ; END_ADR=$3; shift; shift ;; -g ) GATHER="$GATHER$2" ; shift ;; -i ) column_name_long=41 ;; -l ) ACTION=SLH ; if [ -n "$2" ];then case "$2" in p ) ORDER=" order by t2.value desc" ; shift ;; c ) ORDER=" order by t.value desc" ; shift ;; r ) ORDER=" order by physical_reads desc" ; shift ;; g ) ORDER=" order by consistent_gets desc" ; shift ;; cc) ORDER=" order by consistent_changes desc" ; shift ;; b ) ORDER=" order by block_changes desc" ; shift ;; esac fi ;; -len ) column_name_long=$1 ;; -lw ) ACTION="LOCK_WAIT" ;; -n ) SNAP_PAR3=$2 ; shift ;; -o ) ACTION=OVERVIEW;; -m ) FIELD7="machine " ; FIELD4=service_name,;; -p ) ACTION=SNAPER ; SID=$2; shift ;; -plike) PLIKE=$2 ;shift ;; -r ) ACTION="RUNNING" ;; -rf ) ACTION=READ_DUMP_PGA ; TRC=$2 ; shift ;; -rn ) ROWNUM=$2 ; shift ;; -rac ) G=G ; unset FIELD4; EXIT=exit; INST_ID='s.inst_id,';; -s ) SNAP_PAR2=$2 ; shift ;; -siz ) ACTION=PSIZ if [ -n "$2" ];then AND_SESSIONS=" and sid in ($2)" shift ; fi ;; -sup ) ACTION=SUSPEND; SID=$2 ; STYPE=$3; shift ; shift ;; -t ) ACTION="EV_CPU" ; SID=$2 ; shift;; -u ) AND_USER=" s.username = '$2' and " ; shift ;; -ulike) ULIKE=$2 ;shift ;; -v ) set -xv ;; -h ) help;; * ) SID=$1 ; AND_SID=" and s.sid = $1" ; ACTION=SLH ;; esac shift done . $SBIN/scripts/passwd.env . ${GET_PASSWD} $S_USER $ORACLE_SID if [ "x-$CONNECT_STRING" = "x-" ];then echo "could no get a the password of $S_USER" exit 0 fi # ------------------------------------------------------------------------------ # Report Response time breakdown # ------------------------------------------------------------------------------ if [ "$ACTION" = "SUSPEND" ];then if [ -n "$STYPE" ];then if [ "$STYPE" = 's' ];then FACTION=suspend elif [ "$STYPE" = 'r' ];then FACTION=resume else echo "$TYPE should be 's' or 'r' : Invalid suspend/resume action" exit fi else echo "No suspend/resume action" exit fi echo $NN "MACHINE $HOST - ORACLE_SID : $ORACLE_SID $NC" sqlplus -s "$CONNECT_STRING" < 0 ) b, sys.x\$ksled d where i.kslestim > 0 and b.kslesenm (+) = i.indx and nvl(b.time, 0) < i.kslestim and d.indx = i.indx and d.kslednam not in ( 'Null event', 'KXFQ: Dequeue Range Keys - Slave', 'KXFQ: Dequeuing samples', 'KXFQ: kxfqdeq - dequeue from specific qref', 'KXFQ: kxfqdeq - normal deqeue', 'KXFX: Execution Message Dequeue - Slave', 'KXFX: Parse Reply Dequeue - Query Coord', 'KXFX: Reply Message Dequeue - Query Coord', 'PAR RECOV : Dequeue msg - Slave', 'PAR RECOV : Wait for reply - Query Coord', 'Parallel Query Idle Wait - Slaves', 'PL/SQL lock timer', 'PX Deq: Execute Reply', 'PX Deq: Execution Msg', 'PX Deq: Index Merge Execute', 'PX Deq: Index Merge Reply', 'PX Deq: Par Recov Change Vector', 'PX Deq: Par Recov Execute', 'PX Deq: Par Recov Reply', 'PX Deq: Parse Reply', 'PX Deq: Table Q Get Keys', 'PX Deq: Table Q Normal', 'PX Deq: Table Q Sample', 'PX Deq: Table Q qref', 'PX Deq: Txn Recovery Reply', 'PX Deq: Txn Recovery Start', 'PX Deque wait', 'PX Idle Wait', 'Replication Dequeue', 'Replication Dequeue ', 'SQL*Net message from client', 'SQL*Net message from dblink', 'debugger command', 'parallel query dequeue wait', 'pipe get', 'queue messages', 'rdbms ipc message', 'secondary event', 'single-task message', 'slave wait' ) and d.kslednam not like 'resmgr:%' ) ) order by n_major, n_minor, time desc / EOF exit # ------------------------------------------------------------------------------ # Session IO # ------------------------------------------------------------------------------ elif [ "$ACTION" = "SLIO" ];then if [ -z "$SID" ];then echo "I need a Session ID" exit fi sqlplus -s "$CONNECT_STRING" < -- Adapted to Smenu by bpa 10:06:2009 -------------------------------------------------------- set verify off lines 190 pages 66 column tsize new_value total_size column ratio format 99.99 column ds format a20 col ctype for a30 col atype for a30 with t as ( select to_number(substr(fline, 21)) as tsize from $fname30 where regexp_like(fline, 'Total heap size') ) select sum(tsize) as tsize from t ; with c as ( select atype, csize, sum(csize) over() as t_size, &total_size as heap_size from ( select atype, sum(csize) as csize from ( select to_number(regexp_replace(fline,'.*sz=[[:space:]]+([[:digit:]]+)[[:space:]].*','\1')) csize, rtrim(regexp_replace(fline,'.*sz=[[:space:]]+[[:digit:]]+[[:space:]]+([[:alnum:]]+)[[:space:]].*','\1')) atype, rtrim(regexp_replace(fline,'.*["]+(.*)["].*','\1')) ctype, rtrim(regexp_replace(fline,'.*["]+.*["](.*)','\1')) ds from $fname30 where substr(fline, 1, 7) = ' Chunk' and rtrim(regexp_replace(fline,'.*sz=[[:space:]]+[[:digit:]]+[[:space:]]+([[:alnum:]]+)[[:space:]].*','\1')) <> 'free' ) group by atype ) ) select atype, csize, heap_size, (csize/heap_size)*100 as ratio from c union all select 'free', heap_size-t_size, heap_size, ((heap_size-t_size)/heap_size)*100 as ratio from c where rownum = 1 ; with c as ( select ctype, csize, sum(csize) over() as t_size, &total_size as heap_size from ( select ctype, sum(csize) as csize from ( select to_number(regexp_replace(fline,'.*sz=[[:space:]]+([[:digit:]]+)[[:space:]].*','\1')) csize, rtrim(regexp_replace(fline,'.*sz=[[:space:]]+[[:digit:]]+[[:space:]]+([[:alnum:]]+)[[:space:]].*','\1')) atype, rtrim(regexp_replace(fline,'.*["]+(.*)["].*','\1')) ctype, rtrim(regexp_replace(fline,'.*["]+.*["](.*)','\1')) ds from $fname30 where substr(fline, 1, 7) = ' Chunk' and rtrim(regexp_replace(fline,'.*sz=[[:space:]]+[[:digit:]]+[[:space:]]+([[:alnum:]]+)[[:space:]].*','\1')) <> 'free' ) group by ctype ) ) select ctype, csize, heap_size, (csize/heap_size)*100 as ratio from c union all select 'free', heap_size-t_size, heap_size, ((heap_size-t_size)/heap_size)*100 as ratio from c where rownum = 1 ; with c as ( select ds, csize, sum(csize) over() as t_size, &total_size as heap_size from ( select ds, sum(csize) as csize from ( select to_number(regexp_replace(fline,'.*sz=[[:space:]]+([[:digit:]]+)[[:space:]].*','\1')) csize, rtrim(regexp_replace(fline,'.*sz=[[:space:]]+[[:digit:]]+[[:space:]]+([[:alnum:]]+)[[:space:]].*','\1')) atype, rtrim(regexp_replace(fline,'.*["]+(.*)["].*','\1')) ctype, rtrim(regexp_replace(fline,'.*["]+.*["][[:space:]]+ds=(.*)','\1')) ds from $fname30 where substr(fline, 1, 7) = ' Chunk' and regexp_like(fline, 'ds=' ) ) group by ds ) ) select ds, csize, heap_size, (csize/heap_size)*100 as ratio from c union all select 'free', heap_size-t_size, heap_size, ((heap_size-t_size)/heap_size)*100 as ratio from c where rownum = 1 ; EOF # drop now the external table. var=`sqlplus -s "$CONNECT_STRING" < 0 then output(' '); output(chr(8)); output('-- Parameters used: snapper.sql '||'&snapper_options'||' '||to_char(&snapper_sleep)||' ' ||to_char(&snapper_count)||' '||'$SNAP_PAR4_C'); output(chr(8)); output(' '); end if; -- initialize statistic and event name array -- fetch statistic names with their adjusted IDs select * bulk collect into sn_tmp from ( select 'STAT' stype, statistic# - pls_adjust statistic#, name from v\$statname where lv_gather like '%s%' -- union all select 'WAIT', event# + (select count(*) from v\$statname) + 1 - pls_adjust, name from v\$event_name where lv_gather like '%w%' -- &_IF_ORA10_OR_HIGHER union all &_IF_ORA10_OR_HIGHER select 'TIME' stype, stat_id - pls_adjust statistic#, stat_name name &_IF_ORA10_OR_HIGHER from v\$sys_time_model &_IF_ORA10_OR_HIGHER where lv_gather like '%t%' -- union all select ' LAT', l.latch# + (select count(*) from v\$statname) + (select count(*) from v\$event_name) + 1 - pls_adjust statistic#, name from v\$latch l where lv_gather like '%l%' -- union all select ' ENQ', ascii(substr(e.eq_type,1,1))*256 + ascii(substr(e.eq_type,2,1)) + (select count(*) from v\$statname) + (select count(*) from v\$event_name) + (select count(*) from v\$latch) + 1 - pls_adjust statistic#, eq_type from ( select es.eq_type &_IF_ORA10_OR_HIGHER ||' - '||lt.name eq_type, total_req# from v\$enqueue_stat es &_IF_ORA10_OR_HIGHER , V\$lock_type lt &_IF_ORA10_OR_HIGHER where es.eq_type = lt.type ) e where lv_gather like '%e%' ) order by stype, statistic#; -- store these into an index_by array organized by statistic# for fast lookup --output('sn_tmp.count='||sn_tmp.count); --output('lv_gather='||lv_gather); for i in 1..sn_tmp.count loop -- output('i='||i||' statistic#='||sn_tmp(i).statistic#); sn(sn_tmp(i).statistic#) := sn_tmp(i); end loop; -- main sampling loop for c in 1..&snapper_count loop -- print header if required if pagesize > 0 and mod(c-1, pagesize) = 0 then output(rpad('--',141,'-')); output('HEAD, SID, SNAPSHOT START , SECONDS, TYPE, ' ||rpad('STATISTIC',40,' ') ||', DELTA, D/SEC, HDELTA, HD/SEC' ); output(rpad('-',141,'-')); else if pagesize = -1 and c = 1 then output('HEAD, SID, SNAPSHOT START , SECONDS, TYPE, ' ||rpad('STATISTIC',40,' ') ||', DELTA, D/SEC, HDELTA, HD/SEC' ); end if; end if; if c = 1 then snap(d1,s1); else d1 := d2; s1 := s2; end if; -- c = 1 dbms_lock.sleep( (&snapper_sleep - (sysdate - d1)) ); -- dbms_lock.sleep( (&snapper_sleep - (sysdate - d1))*1000/1024 ); snap(d2,s2); changed_values := 0; missing_values_s1 := 0; missing_values_s2 := 0; i :=1; -- iteration counter (for debugging) a :=1; -- s1 array index b :=1; -- s2 array index while ( a <= s1.count and b <= s2.count ) loop delta := 0; -- don't print case when s1(a).sid = s2(b).sid then case when s1(a).statistic# = s2(b).statistic# then delta := s2(b).value - s1(a).value; if delta != 0 then fout(); end if; a := a + 1; b := b + 1; when s1(a).statistic# > s2(b).statistic# then delta := s2(b).value; if delta != 0 then fout(); end if; b := b + 1; when s1(a).statistic# < s2(b).statistic# then output('ERROR, s1(a).statistic# < s2(b).statistic#, a='||to_char(a)||' b='||to_char(b)||' s1.count='||s1.count||' s2.count='||s2.count||' s2.count='||s2.count); a := a + 1; b := b + 1; else output('ERROR, s1(a).statistic# ? s2(b).statistic#, a='||to_char(a)||' b='||to_char(b)||' s1.count='||s1.count||' s2.count='||s2.count||' s2.count='||s2.count); a := a + 1; b := b + 1; end case; -- s1(a).statistic# ... s2(b).statistic# when s1(a).sid > s2(b).sid then delta := s2(b).value; if delta != 0 then fout(); end if; b := b + 1; when s1(a).sid < s2(b).sid then output('WARN, Session has disappeared during snapshot, ignoring SID='||to_char(s2(b).sid)||' a='||to_char(a)||' b='||to_char(b)||' s1.count='||s1.count||' s2.count='||s2.count||' s2.count='||s2.count); a := a + 1; else output('ERROR, Should not be here, SID='||to_char(s2(b).sid)||' a='||to_char(a)||' b='||to_char(b)||' s1.count='||s1.count||' s2.count='||s2.count||' s2.count='||s2.count); end case; -- s1(a).sid ... s2(b).sid i:=i+1; if delta != 0 then changed_values := changed_values + 1; end if; -- delta != 0 end loop; -- while ( a <= s1.count and b <= s2.count ) if pagesize > 0 and changed_values > 0 then output('-- End of snap '||to_char(c)); end if; end loop; -- for c in 1..snapper_count end; / undefine snapper_oraversion undefine snapper_sleep undefine snapper_count undefine snapper_sid undefine _IF_ORA10_OR_HIGHER undefine _IF_DBMS_SYSTEM_ACCESSIBLE col snapper_oraversion clear col dbms_system_accessible clear EOF # ---------------- # Events and CPU time for a session # ---------------- elif [ "$ACTION" = "EV_CPU" ];then if [ -z "$SID" ];then echo echo echo " Error : I need an Session SID\n" echo " sl -t 1 " echo echo exit fi echo "MACHINE $HOSTNAME - ORACLE_SID : $ORACLE_SID Page: 1" sqlplus -s "$CONNECT_STRING" < 0 order by 6 desc / EOF # ---------------- # ASH # ---------------- elif [ "$ACTION" = "ASH" ];then sqlplus -s "$CONNECT_STRING" <= SYSDATE - ($MIN / 1440) GROUP BY DECODE (session_state, 'WAITING', event, NULL), session_state ORDER by 1; EOF # ---------------- # Size # ---------------- elif [ "$ACTION" = "PSIZ" ];then echo "MACHINE $HOSTNAME - ORACLE_SID : $ORACLE_SID Page: 1" sqlplus -s "$CONNECT_STRING" < 0 and v.sid = s. sid and row_wait_obj# = object_id (+); EOF # -------------- # Running # -------------- elif [ "$ACTION" = "RUNNING" ];then if [ -n "$G" ];then AND_INST=" and inst_id = s.inst_id " fi echo "MACHINE $HOSTNAME - ORACLE_SID : $ORACLE_SID Page: 1" sqlplus -s "$CONNECT_STRING" < 0 and v.hash_value = s.sql_hash_value and child_number in (select min (child_number) from ${G}v\$sql where hash_value = s.sql_hash_value $AND_INST) ; EOF # --------- # Overview # --------- elif [ "$ACTION" = "OVERVIEW" ];then echo "MACHINE $HOSTNAME - ORACLE_SID : $ORACLE_SID Page: 1" sqlplus -s "$CONNECT_STRING" <