Oracle下如何收集 Systemstate dump
2: dump (不包括lock element)
10: dump
11: dump + global cache of RAC
256: short stack (函数堆栈)
258: 256+2 -->short stack +dump(不包括lock element)
266: 256+10 -->short stack+ dump
267: 256+11 -->short stack+ dump + global cache of RAC
level 11和 267会 dump global cache, 会生成较大的trace 文件,一般情况下不推荐。一般情况下,如果进程不是太多,推荐用266,因为这样可以dump出来进程的函数堆栈,可以用来分析进程在执行什么操作。但是生成short stack比较耗时,如果进程非常多,比如2000个进程,那么可能耗时30分钟以上。这种情况下,可以生成level 10 或者 level 258, level 258 比 level 10会多收集short short stack, 但比level 10少收集一些lock element data.
2、hanganalyze有如下几种level
10 Dump all processes (IGN state)
5 Level 4 + Dump all processes involved inwait chains (NLEAF state)
4 Level3 + Dump leaf nodes (blockers) in wait chains(LEAF,LEAF_NW,IGN_DMP state)
3 Level2 + Dump only processes thought to be in a hang (IN_HANG state)
1-2 Only HANGANALYZE output, no process dump at all
Oracle官方建议不要超过level 3,一般level 3也能够解决问题,超过level 3会给系统带来额外负担。
3、如何收集相关dump
----------单机
SQL> sqlplus -prelim / as sysdba
SQL> oradebug setmypid
SQL> oradebug unlimit
SQL> oradebug hanganalyze 3
SQL> oradebug hanganalyze 3
SQL> oradebug hanganalyze 3
SQL> oradebug dump systemstate 266 ---266或者258
SQL> oradebug dump systemstate 266
SQL> oradebug dump systemstate 266
SQL> oradebug tracefile_name
------------rac
SQL> sqlplus -prelim / as sysdba
SQL> oradebug setmypid
SQL> oradebug unlimit
SQL> oradebug -g all hanganalyze 3
SQL> oradebug -g all hanganalyze 3
SQL> oradebug -g all hanganalyze 3
SQL> oradebug -g all dump systemstate 266
SQL> oradebug -g all dump systemstate 266
SQL> oradebug -g all dump systemstate 266
SQL> oradebug tracefile_name
4、使用ass来格式化systemstate的
awk -f ass1046.awk orcl1_ora_14290.trc
脚本ass1046.awk
# Usage Instructions
# ~~~~~~~~~~~~~~~~~~
# Usage: [n]awk -f ass.awk fname.trc (But read the Portability Section !!)
#
# This script is tested using "nawk". If your system doesn't have this then
# please try "gawk" and then "awk" (in that order). If issues are seen
# with "gawk" or "awk" then please let me know.
#
# IMPORTANT:
# Some platforms still run the "old" version of awk and this is NOT supported
# as you will see errors such as:
#
# awk: syntax error near line ...
# awk: bailing out near line ...
#
# To test whether you are running the "old" awk version execute the
# following command:
#
# echo " " | awk '{printf("ARGC=%d\n", ARGC)}'
#
# If the result is "ARGC=0" then this indicates that the awk version is "old"
# and this script will probably FAIL.
#
# --------------------------------------------------------------------------
#
# Configuring Ass
# ~~~~~~~~~~~~~~~
#
# By default, 'ass' attempts to dump as much information as possible and
# assumes that the output is to be printed to screen. This means that 'ass'
# runs in its slowest mode. Ass can be changed/speeded up by amending the
# following variables in the BEGIN section :
#
# interactive........... = show indication of processing [default]
# = don't show anything (faster)
# verbose............... = prints additional info [default]
# = don't show info (faster)
# eventdetail........... = prints additional event info for selected events
# [default]
# = don't do the above (faster)
# skipbranch............ = Skip 'branch of' state objects cause by SQL*NET
# loopback sessions etc (default)
# = don't skip 'branch of' transactions
# seqinfo............... = Output sequence number for WAITING processes
# = Do not dump seq# information.
# skipmsess............. = Skip the multi-session reporting
# = Do not skip this (default)
# waitsummary........... = Print summary of all waits (default)
# = Do not print the summary
#
# Portability
# ~~~~~~~~~~~
# ) This uses the nawk extension of functions. Some variants of awk accept
# this (eg HP-UX v10) and others do not. Use nawk if awk fails !!
# ^^^^^^^^^^^^^^^^^^^^^
#
# Alpha OSF/ nawk IBM RS/ awk
# Sun Solaris nawk HPUX awk (v10) ??? (v9)
# Sun SunOS nawk Sequent nawk
#
# ) The Alpha version of awk can only handle fields and will return
# a message like 'awk: Line ..... cannot have more than 99 fields'.
# The w/a: Either change the identified line or use a different platform.
#
# Known Restrictions
# ~~~~~~~~~~~~~~~~~~
# o The script assumes a certain structure to the System State. This means
# that this cannot be used on systemstates produced by MVS or VM.
# [To make it work the first two or three words need to be stripped from]
# [each line in the systemstate trace file. ]
#
# o This has been developed to work with Oracle7. It *may* work with Oracle
# version but this has not been tested.
#
# o It looks like there may be a bug with listing processes that are
# blocking others because they have a buffer s.o. that others are waiting
# on.
#
# o We need to be able to handle multiple-session process state object dumps
# better. Currently, only the LAST session's wait is used. V1.0.15 will
# now ignore "last wait for" entries if we have seen a session for this
# process beforehand. Still not ideal...
#
# o Give "possible deadlock" warnings on processes acquiring TM locks in
# different orders. (Extend to rowcache entries ?).
#
# Coding Notes
# ~~~~~~~~~~~~
# o There's an obscure usage of building the blkres word list. It seems
# that you cannot just say : blkres[a,b] = blkres[a,b] " " newval
# You have to use a temporary variable ('tb' in our case) to achieve this.
# o Sequent doesn't seem to like logical operators being used with regular
# expressions. Hence the 'wait event' section had to be re-written to use
# $ ~ /a/ || $ ~ /b/. Just try the following test :
# NR == && /a/ || /b/ { print }
# o This script has evolved heavily and could now do with a total rewrite
# (possibly using a faster method such as Perl) for speed and memory
# consumption improvements. The RDBMS server is getting better in tracking
# blocking processes so it is probably not worth the effort...
#
# History
# ~~~~~~~
# kquinn.uk v1.0.0 / Created
# kquinn.uk v1.0.1 / Minor changes to run with nawk on OSF1 and AIX
# Blocking Section's output changed slightly
# kquinn.uk v1.0.2 / Dumps object names for library objects
# Now sequent-nawk aware
# First public release
# kquinn.uk v1.0.3 / File I/O wait events now output file, block etc
# kquinn.uk v1.0.4 / Parallel Query Dequeue Reason codes now output
# kquinn.uk v1.0.5 / Added QC to QS code
# Added code to skip 'branch of' state objects
# kquinn.uk v1.0.5 / Output Oracle command based on 'oct:' code.
# (Note that only the PARENT session's command
# code is output).
# Strip carriage returns (^M)
# kquinn.uk v1.0.6 / Indicate dead processes
# kquinn.uk v1.0.7 / Print some more wait information for certain
# wait events and handle waits on the sequence
# enqueue.
# kquinn.uk v1.0.8 / Minor changes
# Changed to accomodate new systemstate format
# so that we identify the start of a systemstate
# correctly once more.
# Added seq# processing for waiting processes.
# Dumped more info for DFS lock acquisition
# kquinn.uk v1.0.9 / Cater for change in 8i enqueue dump
# Dump who waits for who according to the 8i
# wait "blocking sess" information
# kquinn.uk v1.0.10 / sameseq() ignores more irrelevant waits
# getasc() function added [assumes ASCII]
# kquinn.uk v1.0.11 / Added comment about child latches, detect 9i
# trace files, extend sameseq(), print seq info
# for processes not in wait and detect end of
# systemstate.
# kquinn.uk v1.0.12 / Handle 'rdbms ipc reply' and correctly diagnose
# processes blocked by KGL locks.
# kquinn.uk v1.0.13 / Warn about aborted state object dumps
# kquinn.uk v1.0.14 / Tidy up enqueue info, IPC dump and rowcache info
# Other minor changes.
# kquinn.uk v1.0.15 / Initial attempt to handle multi-sessions
# by ignoring "last wait" entries
# kquinn.uk v1.0.16 / Support 9i lock element dumps
# Record pin instance lock blockers
# Report on libcache load locks
# Warn when systemstate level is too low
# Catch "dictionary object cache" waits
# Handle 10g seq format
# kquinn.uk v1.0.17 / Handle mutex state objects
# kquinn.uk v1.0.18 / Handle v10. BH state object
# kquinn.uk v1.0.19 / Capture time of systemstate
# kquinn.uk v1.0.20 / Handle 10g wait blocking format
# kquinn.uk v1.0.21 / Correct a bug spotted by Alper Ikinci
# kquinn.uk v1.0.22 / Initial 11g support
# kquinn.uk v1.0.23 / Correct "Blockers According to" processing
# Added wait summary
# kquinn.uk v1.0.24 / Latch improvements
# kquinn.uk v1.0.25 / Mutex changes
# kquinn.uk v1.0.26 / Isolate the self-deadlocking resource and
# dump rowcache names for later releases
# kquinn.uk v1.0.27 / Cygwin portability change
# kquinn.uk v1.0.28 / Stop ass.awk when we hit PSEUDO process
# kquinn.uk v1.0.29 / Handle enqueue conversion case
# kquinn.uk v1.0.30 / Handle newer form of dead processes
# kquinn.uk v1.0.31 / Support 11.2 kgl locks/pins
# kquinn.uk v1.0.32 / Print warning if "SYSTEM STATE" not seen.
# kquinn.uk v1.0.33 / Dump latch waiter information
# kquinn.uk v1.0.34 / Handle 11.2 LibraryObjectLoadLock
# kquinn.uk v1.0.35 / Print warning if "PROCESS STATE" seen
# (if seen -during- systemstate we can stop)
# kquinn.uk v1.0.36 / Added usage notes regarding nawk, gawk etc.
# kquinn.uk v1.0.37 / Added notes to determine whether the "old" awk
# version is being used, which is not supported.
# kquinn.uk v1.0.38 / Correctly process Pids with zero (e.g. Pid )
# kquinn.uk v1.0.39 / Handle bug
# kquinn.uk v1.0.40 / Remove QC <-> Slave mapping. (It has been
# broken from at least v11 due to changes to
# state object dumps).
# kquinn.uk v1.0.41 / Dump the Oracle Pid for "possible holder".
# kquinn.uk v1.0.42 / Handle <ctrl>-M binary sequences so that
# the script can be ftp'd in ascii mode
# kquinn.uk v1.0.43 / Correct 12c libcache name handling
# kquinn.uk v1.0.44 / Handle 11g buffer state object
# Make a summary section conditional
# Dump final blocker information, if present.
# kquinn.uk v1.0.45 / Remove 8i "Blockers According to Tracefile Wait
# Info" section and add pid to sid mapping.
# kquinn.uk v1.0.46 / Support 12.2 timestamps and don't print [DEAD]
# for PMON. Also, add warning about process
# blocked by, *and* waiting on the same mutex.
#
# Current Enhancement Requests Oustanding
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# o For enqueue conversations, detect when we have another session that is
# blocked by our enqueue-converting session and highlight this
# o Handle multiple session better. We could elect to handle all session
# state objects or choose the most relevant one (e.g. ones that are in
# BSY state or are blocked).
# o Pick out error code in PQO Queue Ref's
# o Test concatenating all array elements so that we effectively use singular
# arrays. This may speed the processing depending upon how the implementation
# of awk uses multi-dimensional arrays.
# o Consider dumping a quick "transaction profile" of the database to get
# an idea about update activity, DDL etc.
#
##############################################################################
# Any failure cases or suggested improvements then please email #
# kevin.p.quinn@oracle.com with the details and the systemstate file (if #
# relevant). Thanks. #
############################################################################## # Function : add_resource
# ~~~~~~~~~~~~~~~~~~~~~~~
function add_resource (list, item) {
if (index(list, item))
return list;
else
return list " " item;
}
# Function : warn_level
# ~~~~~~~~~~~~~~~~~~~~~
function warn_level () {
printf("Warning: No wait information seen - the systemstate level may have\n");
printf(" been too low. Please use 10 or above.\n");
}
# Function : sameseq
# ~~~~~~~~~~~~~~~~~~
function sameseq(ev1, ev2, seq1, seq2) {
#printf("sameseq: Comparing :\n");
#printf("Ev=(%s) seq=(%s)\n", ev1, seq1);
#printf("against Ev=(%s) seq=(%s)\n", ev2, seq2);
if (!seq1) return ;
if (seq1 != seq2) return ;
if (ev1 != ev2) return ; if (ev1 ~ "'rdbms ipc message'" ||
# ev1 ~ "'rdbms ipc reply'" ||
ev1 ~ "'smon timer'" ||
ev1 ~ "Net message from client'" ||
ev1 ~ "Net message to client'" ||
ev1 ~ "Net message from dblink'" ||
ev1 ~ "'pmon timer'")
return ;
return ;
}
# Function : min
# ~~~~~~~~~~~~~~
function min(one, two) {
return (one<two?one:two);
}
# Function: hx2dec
# ~~~~~~~~~~~~~~~~
function hx2dec(inhex) {
_table["A"]=; _table["B"]=;_table["C"]=;_table["D"]=;_table["E"]=;
_table["F"]=;
_res = ;
_ll = length(inhex);
for (_i=; _i<=_ll; _i++)
{
_res *= ;
_tok=toupper(substr(inhex,_i,)); if ("ABCDEF" ~ _tok)
_res += _table[_tok];
else
_res += _tok; # coerce to numeric } # end for return _res;
}
# Function : getasc
# ~~~~~~~~~~~~~~~~~
function getasc(_str) {
_val = hx2dec(_str);
# Use string comparison to test for a valid value :
if (_val < || _val > ) return "?";
return substr(ascii_str,_val-+,); # ASCII 'A' = 0x41 =
}
# Function: procevent
# ~~~~~~~~~~~~~~~~~~~
function procevent (str) {
if (!eventdetail) return str;
realev = str;
sub("^.* for ", "", str);
sub("holding ", "", str);
sub("acquiring ", "", str);
# printf("DBG> String = '%s'\n", str);
if (str == "'db file sequential read'"||str == "'db file scattered read'" ||
str == "'db file parallel write'" ||str == "'db file sequential write'" ||
str == "'buffer busy waits'" || str == "'free buffer waits'" ||
str == "'buffer deadlock'" || str == "'parallel query qref latch'")
{
getline; sub(CR,""); gsub("="," ");
realev = realev " (" $ $ $ ")";
}
else if (str == "'pipe get'")
{
getline; sub(CR,"");
realev = realev " (" $ ")";
}
else if (str == "'parallel query dequeue wait'")
{
getline; sub(CR,"");
gsub("="," ");
realev = realev " (" $ $ $ ")";
}
else if (str == "'enqueue'" || str == "'DFS lock acquisition'")
{
getline; sub(CR,""); gsub("="," ");
# For now let's not do anything too clever !
tm1=getasc(substr($,,));
tm2=getasc(substr($,,));
realev = realev " (" tm1 tm2 " id=" $ $ ")";
############################################
### The following tends to crowd the output.
############################################
#else
# realev = realev " (" $ $ $ ")";
}
else if (str == "'rdbms ipc reply'") # v1.0.12
{
# waiting for 'rdbms ipc reply' blocking sess=0x0 seq= wait_time=
# from_process=c, timeout=147ada4, = getline; sub(CR,""); gsub("="," ");
sub(",","",$);
_proc = hx2dec($);
realev = realev " (" $ "=" _proc ")";
waitres[sstate, pid] = "IPC " _proc;
blkres[sstate, "IPC " _proc] = _proc;
} return realev;
}
# Function: print_blkr_header
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
function print_blkr_header()
{
printf("\nBlockers According to Tracefile Wait Info:");
printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("1. This may not work for 64bit platforms. ");
printf("See bug 2902997 for details.\n");
printf("2. If the blocking process is shown as 0 then ");
printf("that session may no longer be\n present.\n");
printf("3. If resources are held across code layers then ");
printf("sometimes the tracefile wait\n ");
printf("info will not recognise the problem.\n\n");
} ##############################################################################
# S T A R T O F P R O C E S S I N G #
# #
# BEGIN Section: #
# Can amend 'interactive', 'verbose','skipmsess' and 'eventdetail'. #
##############################################################################
BEGIN { version="1.0.46"; lwidth=; interactive=; verbose=;
eventdetail=; skipbranch=; seqinfo=; skipmsess=;
waitsummary=; waitsummary_thresh=;
EQCNV=; CR="\r";
util_url="http://gbr30026.uk.oracle.com:81/Public/Utils.html#ass";
doc_url ="http://gbr30026.uk.oracle.com:81/Public/TOOLS/Ass.html";
emailid ="kevin.p.quinn@oracle.com";
UNKNOWN_PID="???";
TERM="------------------ooOoo------------------";
tx1="Above is a list of all the processes. If they are waiting for a resource";
tx2="then it will be given in square brackets. Below is a summary of the";
tx3="waited upon resources, together with the holder of that resource.";
tx4="Notes:\n\t~~~~~";
tx5=" o A process id of '???' implies that the holder was not found in the";
tx6=" systemstate. (The holder may have released the resource before we";
tx7=" dumped the state object tree of the blocking process).";
tx8=" o Lines with 'Enqueue conversion' below can be ignored *unless* ";
tx9=" other sessions are waiting on that resource too. For more, see ";
tx10=" http://gbr30026.uk.oracle.com:81/Public/TOOLS/Ass.html#enqcnv)";
tx11=" o You might see a process blocked on a mutex wait event but also ";
tx12=" reported as holding the same mutex. You will need to check the ";
tx13=" processstate dump as we might have been waiting at the start of the ";
tx14=" process dump but have acquired it before the dump completed.";
br1="WARNING: The following is a list of process id's that have state";
br2=" objects that are NOT owned by the parent state object and as";
br3=" such have been SKIPPED during processing. (These are typically";
br4=" SQL*Net loopback sessions)."; abort_err="WARNING: The following processes had a corrupted / in-flux state object tree :"; cmdtab[]="Create Table"; cmdtab[]="Insert";cmdtab[]="Select";
cmdtab[]="Create Cluster";cmdtab[]="Alter Cluster";cmdtab[]="Update";
cmdtab[]="Delete";cmdtab[]="drop Cluster";cmdtab[]="Create Index";
cmdtab[]="Drop Index";cmdtab[]="Alter Index";cmdtab[]="Drop Table";
cmdtab[]="Create Sequence";cmdtab[]="Alter Sequence";
cmdtab[]="Alter Table";cmdtab[]="Drop Sequence";
cmdtab[]="Grant";cmdtab[]="Revoke";cmdtab[]="Create Synonym";
cmdtab[]="Create View";cmdtab[]="Drop View";
cmdtab[]="Create Procedure";cmdtab[]="Alter Procedure";
cmdtab[]="ALter Procedure";cmdtab[]="Alter Tablespace";
cmdtab[]="Alter Session";cmdtab[]="Commit";cmdtab[]="Rollback";
cmdtab[]="PL/SQL Execute";cmdtab[]="Explain";cmdtab[]="Create User";
cmdtab[]="Create Role";cmdtab[]="Drop User";cmdtab[]="Drop Role";
cmdtab[]="Analyze Table";cmdtab[]="Analyze Index";
cmdtab[]="Analyze Cluster";cmdtab[]="Alter Profile";
cmdtab[]="Drop Procedure";cmdtab[]="Truncate Table";
cmdtab[]="Alter View";cmdtab[]="Create Pkg";cmdtab[]="Alter Pkg";
cmdtab[]="Call Method"; cmdtab[]="Upsert"; ascii_str="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ## Child latch Warning array
cw[]="Some processes are being blocked waiting for child latches.\n";
cw[]="At the moment this script does not detect the blocker because the";
cw[]="child latch address differs to the parent latch address. To manually";
cw[]="detect the blocker please take the following steps :";
cw[]="1. Determine the TYPE of latch (Eg library cache) that is involved.";
cw[]="2. Search the source trace file for a target of :";
cw[]=" holding.*Parent.*library cache";
cw[]=" (Assuming we have a child library cache and have vi-like regular expressions)\n";
cw[]="If this shows nothing then the blocker may have released the resource";
cw[]="before we got to dump the state object tree of the blocked process.\n";
cw[]="A list of processes that hold parent latches is given below :\n";
CHILD_WARN=; pstr[]="The following processes have the PIN INSTANCE LOCK set in a way in";
pstr[]="which other pin requesters may be blocked. Please use the 'id='";
pstr[]="column to correlate potential blockers across nodes."; padstrarr[]=""; padstrarr[]=" "; padstrarr[]=" "; padstrarr[]=" ";
padstrarr[]=" "; padstrarr[]=" "; padstrarr[]=" ";
} # Start of trace file
# ~~~~~~~~~~~~~~~~~~~
# Oracle7 Server Release 7.1.6.2.
# Oracle8 Enterprise Edition Release 8.0.5.0.
/^Oracle7 Server Release \./ { rdbms_ver = $; next }
/^Oracle8 .* .* Release \./ { rdbms_ver = $; next }
/^Oracle8i / { rdbms_ver = $(NF-); a8ienabled=; next }
/^Oracle9i / { rdbms_ver = $(NF-);
a9ienabled= a8ienabled=; next }
/^Oracle10i / { rdbms_ver = $(NF-);
a10ienabled=a9ienabled=a8ienabled=; next }
/^Oracle Database [][cg]/ { sub("^Oracle.*Release ", "");
rdbms_ver = $;
a10genabled=a10ienabled=a9ienabled=;
a8ienabled=; next } # Strip Carriage returns
{ sub("\r$", ""); } # Timestamp assumed to be of the form:
#
# *** -- ::20.646
# *** SESSION ID:(25.119) -- ::02.885
#
# See ksdddt() which prints this form regardless of NLS settins
#
# 12.2 form is:
# *** --04T19::39.650204+: # Use a pattern that should be "good enough"
/^\*\*\* [][-]*-[-]*-[-]* [-]*:.*:/ { tempts=$ " " $; next }
/^... SESSION ID:/ { tempts=$ " " $; next }
/^\*\*\* [][-]*-[-]*-[-]*T[-]*:.*:/{ sub("T", " ");
sub("\+", " ");
tempts=$ " " $;
ts12_2=;
next;
} # Start of Systemstate
# ~~~~~~~~~~~~~~~~~~~~
/^SYSTEM STATE/ { printf("\nStarting Systemstate %d\n", ++sstate);
tstamp[sstate] = tempts;
# Even tho' we don't need to initialise scalers
# before they are referenced (they implicitly default
# to ) it seems that we must do this for arrays.
platch[sstate] = ;
lcount=; insystate=; inbranch=; next } /^END OF SYSTEM STATE/ { insystate=; next }
/^PSEUDO PROCESS for group/ { insystate=; next }
/^PROCESS [-][-]*:/ { tmpid=$; sub(":","", tmpid);
numpid = tmpid+; #coerce
if (numpid>hipid) hipid=numpid;
} # Skipped Lines
# ~~~~~~~~~~~~~
insystate!= { next }
# Used for PQO--flds and two are good enuf
# Do NOT skip additional processing (ie no next) /^ *SO:/ { myso=$; in_buffer_so=; } # record the last pid seen. If we haven't seen one then we don't care.
/^PROCESS STATE/ { insystate=;
pstate_seen[sstate]=numpid;
next;
}
/SHUTDOWN: waiting for logins to complete/ { next } # Code to skip 'branch of' state objects which are caused by silly things
# such as SQLNET loopback sessions
skipbranch && inbranch > { tmp = $;
sub(branchstr, "", tmp);
if (tmp !~ "^ ")
inbranch = ;
} /^ *branch of *$/ { if (skipbranch)
{
sub("branch of.*", ""); branchstr="^" $;
inbranch=length(branchstr);
branchlst[sstate]=branchlst[sstate] " " pid;
next
}
} # Start of New Process
# ~~~~~~~~~~~~~~~~~~~~
/PROCESS [-][-]*:/ { pid=$;
inbranch=;
# Need to use pidarray to avoid "holes"
# in processes causing us problems.
pidarray[sstate, ++pidcnt[sstate]] = pid;
handle="";
# v1.0.9 - keep max pid for use with a8iblk[]
if (numpid > maxpid) maxpid = numpid;
if (!interactive) next;
if (++lcount > lwidth) lcount=;
printf("%s", lcount==? "\n.":".");
next } # Oracle Command
# ~~~~~~~~~~~~~~
# oct: , prv: , user: /MRCHTMH
/^ *oct: .*, prv:/ { tmp=$; sub(",", "",tmp);
# Only output the parent session's command.
if (!oct[sstate, pid]) oct[sstate, pid]=tmp;
next } # Final Blocker
# ~~~~~~~~~~~~~
# There is at least one session blocking this session.
# Dumping direct blocker(s):
# inst: , sid: , ser:
# Dumping final blocker:
# inst: , sid: , ser:
/^ *Dumping final blocker:/ { getline;
if ($ ~ "inst:")
{
sub("^ *", "");
fblk[sstate, pid] = $
}
} # Aborted State Object Dump
# ~~~~~~~~~~~~~~~~~~~~~~~~~
# Let's just assume one aborted state object tree per session for now
/^Aborting this subtree dump/ { aborted[pid] = NR;
abort_seen[sstate] = ;
ablist[sstate] = ablist[sstate] " " pid;
next; } # Capture Seq
# ~~~~~~~~~~~
# last wait for 'db file sequential read' seq= wait_time= /waiting for .*seq=.*wait_time/ { if (seqinfo)
{
tmp = $;
sub("^.*seq", "seq", tmp);
sub("wait.*$", "", tmp);
seq[sstate, pid] = tmp;
}
## v1.0.9 - See if we have the new 8i "blocking sess" token and store this
## for later use as well.
#
# waiting for 'enqueue' blocking sess=0x800618a4 seq= wait_time=
# name|mode=, id1=, id2=a
#
## v1.0.23 - Format changed so need to isolate the session differently
# if ($ ~ "blocking sess=" &&
$ !~ "blocking sess=0x0" &&
$ !~ "blocking sess=0x.nil")
{
tmp = $;
sub("^.*sess=", "", tmp);
sub(" .*$", "", tmp);
sub("0x", "", tmp);
a8iblk[sstate, numpid] = tmp;
#printf("DBG> a8iblk[%d, %d] = '%s'\n", sstate, numpid, tmp);
} if (waitsummary)
{
tmp = $;
sub("^.*waiting for '", "", tmp);
sub("'.*$", "", tmp);
gsub(" ", "_", tmp); waitsum[sstate, tmp]++;
if (!index(waitlist[sstate], tmp))
waitlist[sstate]=waitlist[sstate] " " tmp;
}
} ## v1.0.14 - Remove the following code otherwise we will report that these
## processes are "stuck" when they are not, they are busy doing
## something!
#/last wait for '/ { if (seqinfo)
# seq[sstate, pid] = $(NF-);
# } ## v1.0.9 - To make use of a8iblk array we need to capture the session state
## object. # Capture Session S.O.
# ~~~~~~~~~~~~~~~~~~~~
# Old formats:
# (session) trans: 801382dc, creator: , flag: () USR/- BSY/-/-/-/-/-
# (session) sid: trans: , creator: 10600193b0, flag: () ...
#
# v1.0.45 - 11g format:
# (session) sid: ser: trans: 0x0, creator: 0x0 /^ *.session. sid:/ { sidlist[sstate, pid] = add_resource(sidlist[sstate, pid],
$);
#serlist[sstate, pid] = add_resource(serlist[sstate, pid],
#$);
next;
} # Wait Event Information
# ~~~~~~~~~~~~~~~~~~~~~~
# Gather the current wait event information for a simple overview of the
# 'Waiter' information summarised at the end.
# # v1.0.22: Convert 11g format to pre-11g format
$ ~ "^ *[0-9]*: *waiting for .*'" { sub("[0-9]*:", ""); } $ ~ "last wait for .*'" ||
$ ~ "acquiring .*'" ||
$ ~ "^ *waiting for .*'" ||
$ ~ "holding .*'" { # v1.0.15: detect multiple sessions
if (wait_event[sstate, pid])
{
msess[sstate] = add_resource(msess[sstate],
pid);
# ignore non-waiting sessions
if ($ ~ "last wait for") next; }
tmp=$;
# Just keep event name
sub("' .*$", "'", tmp);
sub("^ *","", tmp);
wait_event[sstate, pid] = procevent(tmp);
} /^ *holding .*Parent.*level=/ { pl_pid[sstate, platch[sstate]] = pid;
tmp=$;
sub("^ *holding *","", tmp);
pl_str[sstate, platch[sstate]] = tmp;
platch[sstate]++; } # Spot Dead Processes
# ~~~~~~~~~~~~~~~~~~~
# (process) Oracle pid=, calls cur/top: 22060e34/22060e34, flag: () DEAD
/(process).*flag:.*DEAD/ { isdead[sstate,pid]=; }
# newer form:
# O/S info: user: oracle, term: UNKNOWN, ospid: (DEAD)
# (skip if pid==, which is PMON)
/ospid:.*DEAD/ { if (pid != "1:") isdead[sstate,pid]=; } # RESOURCE: Latch
# ~~~~~~~~~~~~~~~
# Example:
# waiting for 80108e04 shared pool level= state=free
# wtr=80108e04, next waiter
# holding 80108eec library cache pin level= state=busy
#
/^ *waiting for *[a-f0-][a-f0-]* / { waitres[sstate, pid] = "Latch " $;
if (verbose)
{
if (!objname[sstate, "Latch " $])
{
tmp = $;
sub("^ *waiting for *[a-f0-9]* ","");
sub(" level.*$","");
objname[sstate, "Latch " tmp] = $; curlatch = "'" $ "'"; # used later
}
else curlatch=objname[sstate, "Latch " $];
}
next } # v1.0.24: With later versions (10g) we can -also- see this form:
#
# holding (efd=) 380142c78 Child shared pool level= child#=
#
# so strip out the (efd=.*) /^ *holding *.efd=/ {
sub(" .efd=[0-9][0-9]*. ", " ");
}
/holding *[a-f0-]* / { tb = blkres[sstate, "Latch " $];
tb = add_resource(tb,pid);
blkres[sstate, "Latch " $] = tb;
if (verbose && !objname[sstate, "Latch " $])
{
tmp = $;
sub("^ *holding *[a-f0-9][a-f0-9]* ","");
sub(" level.*$","");
objname[sstate, "Latch " tmp] = $;
}
next }
/acquiring *[a-f0-]* / { tb = blkres[sstate, "Latch " $];
tb = add_resource(tb,pid);
blkres[sstate, "Latch " $] = tb;
if (verbose && !objname[sstate, "Latch " $])
{
tmp = $;
sub("^ *acquiring *[a-f0-9]* ","");
sub(" level.*$","");
objname[sstate, "Latch " tmp] = $;
}
next } # v1.0.33 - Dump additional latch wait information, if present
#
# waiters [orapid (seconds since: put on list, posted, alive check)]:
# (, , )
# (, , )
# (, , )
# ..
# waiter count=
# gotten times wait, failed first sleeps
# gotten times nowait, failed:
# possible holder pid = ospid= /^ *waiter count=[-]/ { if (!verbose) next; gsub("^ *waiter count=", "");
wcnt = $+; # coerce to numeric getline;getline;getline;
if ($ ~ "possible holder pid")
{
gsub("^.* pid =", "");
wtrpid=$;
gsub(".* ospid=", "");
wtrospid=$; # might be a string on some OS
}
else wtrpid = -; wtrcount[sstate]++;
wtrtmp=sprintf("Pid %d is blocked waiting for latch",
pid);
wtrtmp=sprintf("%s %s with %d waiters.",
wtrtmp, curlatch, wcnt);
if (wtrpid != -)
{
wtrtmp=wtrtmp "\nPossible holder is Pid ";
wtrtmp=wtrtmp wtrpid " (ospid " wtrospid ").";
}
wtrstr[sstate, wtrcount[sstate]] = wtrtmp;
} # RESOURCE: Enqueue
# ~~~~~~~~~~~~~~~~~
# Example:
# (enqueue) TX--
# lv:
# res:c07c3e90, mode: X, prv: c07c3e98, sess: c1825fc8, proc: c180d338
#
/\(enqueue\) <no resource>/ { next } # Skip this /\(enqueue\)/ { tmp = $;
eqres = "Enq " tmp;
getline; getline; sub(CR,""); ## v1.0.9 - Under 8i we now print a space following the "res:" token above
## which means that we can no longer rely on word position so let's
## just search for the fact that the line CONTAINS "mode:" or
## "req:". ## V1.0.29:
## Sometimes a session might be in the process of converting a lock which
## would appear as follows:
##
## (enqueue) TM-000063A0- DID: --0000075B
## lv: res_flag: 0x7
## res: 0x3fe7eb850, mode: SX, req: SSX, lock_flag: 0x0
##
## Our session both blocks and is blocked and prior to V1.0.29 it would be
## reported as a self-deadlock. We still need to record the blocked and
## is-blocked for comparison with other sessions but lets record the fact
## that we are converting and then avoid the bogus self-deadlock message. mode_seen = req_seen = ;
if ($ ~ "mode:")
{
mode_seen = ;
tb = blkres[sstate, eqres];
tb = add_resource(tb , pid);
blkres[sstate, eqres] = tb;
} if ($ ~ "req:")
{
req_seen = ;
waitres[sstate, pid] = eqres;
} ## The code below tries to record the correct state to determine whether this
## might be a blocker. If we -ever- see just a mode: or a req: then we are
## potentially interested in the session so we ignore any other enqueue
## conversion on this resource. If we see -both- a mode: and a req: then we
## set this as an enqueue conversion iff we haven't seen a previous enqueue
## conversion on this resource. if (mode_seen && req_seen)
{
if (!eqconv[sstate, pid, eqres])
eqconv[sstate, pid, eqres] = EQCNV;
else
eqconv[sstate, pid, eqres] = EQCNV+;
}
else if (mode_seen || req_seen)
eqconv[sstate, pid, eqres] = EQCNV+; ## V1.0.29: mode isn't correct with more recent versions and isn't reported
## so let's just comment it out for now.
# sub(", prv.*$", "");
# mode[sstate, pid, tmp] = $NF;
next } # RESOURCE: Row Cache Enqueue
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example:
# row cache enqueue: count= session=c1825fc8 object=c146e960, request=S
# row cache parent object: address=c146e960 type=(dc_tables)
#
/row cache enqueue:.*mode/ { tb = blkres[sstate, "Rcache " $]; tb = add_resource(tb, pid);
blkres[sstate, "Rcache " $] = tb;
if (verbose && !objname[sstate, "Rcache " $])
{
mode[sstate, pid, $] = $;
tmp = $; getline; sub(CR,"");
# Oracle version introduced another line
if ($ !~ "row cache parent object")
{
getline; sub(CR,"");
}
objname[sstate, "Rcache " tmp] = $;
sub(".*type=.*dc_", "(dc_",
objname[sstate, "Rcache " tmp]);
}
next } /row cache enqueue:/ { waitres[sstate, pid] = "Rcache " $;
if (verbose && !objname[sstate, "Rcache " $])
{
mode[sstate, pid, $] = $;
tmp = $;
getline; sub(CR,"");
# Oracle version introduced another line
if ($ !~ "row cache parent object")
{
getline; sub(CR,"");
}
objname[sstate, "Rcache " tmp] = $;
sub(".*type=.*dc_", "(dc_",
objname[sstate, "Rcache " tmp]);
}
next } # RESOURCE: Mutex
# ~~~~~~~~~~~~~~~
# Example:
# KGX Atomic Operation Log 0x263407c8
# Mutex 0x2587ea64(, ) idn 22373e0c oper SHRD
# Cursor Pin uid efd whr slp
# opr= pso=0x263f8674 flg=
# pcs=0x2587ea64 nxt=(nil) flg= cld= hd=0x267b6368 par=0x2587e860
# ct= hsh= unp=(nil) unn= hvl=2587e744 nhv= ses=0x29154334
# hep=0x2587eaac flg= ld= ob=0x2586bbe0 ptr=0x25867010 fex=0x25866ff8
#
# Bug : Only use low bytes for idn /^ *Mutex \(nil\)/ { next; } # We have a mutex holder if we see "Mutex 0x2587ea64(0, 1)" where
# this field is not ---------+
/^ *Mutex/ { mxmode=$NF;
hldr=$;
# v1.0.27: The previous version tried to use the code:
# sub("^.*\(", "", hldr);
# but this isn't portable (it fails on Cygwin) and isn't
# strictly correct. See
# http://www.gnu.org/manual/gawk/html_node/Gory-Details.html
#
# For now, let's just use index() and substr(). ## printf("hldr was '%s', but now ", hldr);
sub(",", "", hldr);
## printf(" =>'%s' and lastly ", hldr);
brket = index(hldr, "(");
## printf("(brk=%d) ", brket);
if (brket) brket++; # bump passed the '('
hldr = substr(hldr, brket);
## sub("^.*\x28", "", hldr);
## sub("^.*\(", "", hldr);
## printf("'%s'\n", hldr);
sub("^.*idn ", "");
mid=$;
# handle bug
idnlen=length(mid);
if (idnlen > )
mid=substr(mid, idnlen-+); # We have: GET_SHRD, SHRD, SHRD_EXAM, REL_SHRD, GET_EXCL,
# EXL, REL_EXCL, GET_INCR, INCR_EXAM, GET_DECR, DECR_EXAM,
# RELEASED, EXCL_SHRD, GET_EXAM, EXAM
if (mxmode ~ "GET_")
{
waitres[sstate, pid] = "Mutex " mid;
}
else if (hldr != "" && mxmode != "NONE")
{
tb = blkres[sstate, "Mutex " mid];
tb = add_resource(tb, pid);
blkres[sstate, "Mutex " mid] = tb;
}
} # RESOURCE: Dictionary Object Cache Enqueue
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example:
# dictionary object cache enqueue
# address: 7000002754e8858 next: 7000002754e88b8 prev:
# process: 7000002623f2400 state: WAIT /^ *dictionary object cache enqueue/ { getline; getline;
if ($NF == "REPL")
{
tb = blkres[sstate, "DictObj"];
tb = add_resource(tb, pid);
blkres[sstate, "DictObj"] = tb;
}
else
{
waitres[sstate, pid] = "DictObj";
}
next;
} # RESOURCE: Library Object Load Lock
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example:
# LIBRARY OBJECT LOAD LOCK: lock=c00000007a366fe8
# process=c000000077bc1148 object=c00000007baac6c8 request=X mask=
#
# Or, under 11.2.0.2:
#
# LibraryObjectLoadLock: Address=0x213259120 User=0x24ebb79e0 Handle=0x2135c2900
# Mode=X Mask= LockCount=
#
# Due to bug , we might not have a RequestMode=.. value so use Mode=
# to determine holder and the absence of Mode= to indicate waiter /LIBRARY OBJECT LOAD/ { getline;
gsub("=", " ");
if ($ == "request")
{
waitres[sstate, pid] = "LOAD: " $;
mode[sstate, pid, $] = $;
}
else
{
tb = blkres[sstate, "LOAD: " $];
tb = add_resource(tb, pid);
blkres[sstate, "LOAD: " $] = tb;
mode[sstate, pid, $] = $;
}
} /^ *LibraryObjectLoadLock:/ { gsub("=", " ");
if ($ ~ "Mode")
{
tb = blkres[sstate, "LOAD: " $];
tb = add_resource(tb, pid);
blkres[sstate, "LOAD: " $] = tb;
mode[sstate, pid, $] = $;
}
else
{
waitres[sstate, pid] = "LOAD: " $;
mode[sstate, pid, $] = $;
}
} # RESOURCE: Library Object Pin/Lock
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example:
# LIBRARY OBJECT PIN: pin=c0f3aa90 handle=c15bcac0 mode=S lock=c0f3b840
# LIBRARY OBJECT LOCK: lock=c0f3b840 handle=c15bcac0 mode=N
#
/LIBRARY OBJECT .*mod/ { if ($ != "mode=N") # Ignore Null locks
{
tb = blkres[sstate, $ " " $];
tb = add_resource(tb, pid);
blkres[sstate, $ " " $] = tb;
mode[sstate, pid, $] = $;
next;
}
} /LIBRARY OBJECT .*req/ { waitres[sstate, pid] = $ " " $;
mode[sstate, pid, $] = $; next } # 11g Example:
# LibraryObjectLock: Address=7b6910a0 Handle=7b65e758 Mode=X ...
# LibraryObjectLock: Address=7b709208 Handle=7b6c22a0 RequestMode=X
# LibraryObjectPin: Address=7b6f9ab8 Handle=7b65e758 Mode=X .. /^ *LibraryObjectLock: .* Mod/ { if ($ != "Mode=N") # Ignore Null locks
{
tb = blkres[sstate, "LOCK: " $];
tb = add_resource(tb, pid);
blkres[sstate, "LOCK: " $] = tb;
mode[sstate, pid, $] = $;
next;
}
} /^ *LibraryObjectLock: .*Req/ { waitres[sstate, pid] = "LOCK: " $;
mode[sstate, pid, $] = $; next } /^ *LibraryObjectPin: .* Mod/ { if ($ != "Mode=N") # Ignore Null locks
{
tb = blkres[sstate, "PIN: " $];
tb = add_resource(tb, pid);
blkres[sstate, "PIN: " $] = tb;
mode[sstate, pid, $] = $;
next;
}
} /^ *LibraryObjectPin: .*Req/ { waitres[sstate, pid] = "PIN: " $;
mode[sstate, pid, $] = $; next } /Rel-Stack=/ { kglstack=; } # RESOURCE: Pin instance lock
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# LOCK INSTANCE LOCK: id=LB3791b1418e1e06ff
# PIN INSTANCE LOCK: id=NB3791b1418e1e06ff mode=S release=T flags=[]
# INVALIDATION INSTANCE LOCK: id=IV006ed60b11172935 mode=S /^ *PIN INSTANCE LOCK:.*release=T/ { tcnt = pinins[sstate];
# are we a new process ? If so, bump count
if (pinins_pid[sstate, tcnt] != pid)
{
tcnt = ++pinins[sstate];
pinins_pid[sstate, tcnt] = pid;
}
pinins_pin[sstate, pid] = add_resource(pinins_pin[sstate, pid], $);
} # RESOURCE: Cache Buffer
# ~~~~~~~~~~~~~~~~~~~~~~
# Example:
# (buffer) (CR) PR: FLG:
# kcbbfbp : [BH: befd8, LINK: 7836c] (WAITING)
# BH # (0xbefd8) dba: class ba: a03800
# hash: [7f2d8,b47d0], lru: [,b1b50]
# use: [78eb4,78eb4], wait: [79cf4,]
# st: READING, md: EXCL, rsop:
# cr:[[scn: 0.00000000],[xid: 00.00.],[uba: 00.00.], sfl: ]
# flags: only_sequential_access
# L:[0.0.] H:[0.0.] R:[0.0.]
# Using State Objects
#
/^ *kcbbfbp/ { if (a10genabled)
blmode = $; # 'kcbbfbp :' became 'kcbbfp:'
else
blmode = $; # v1.0.44: Instead of using "getline" calls to try
# to locate the buffer state, let awk handle the
# search for "BH ". Note that this token might be
# missing so we reset the flag below when we see a
# new state object.
in_buffer_so = ;
} # v1.0.44: Now try to complete the buffer state object processing
/^ *BH/ &&
in_buffer_so == { if (a10genabled)
dba = $;
else
dba = $; if (blmode == "(WAITING)" || blmode == "EXCLUSIVE" )
waitres[sstate, pid] = "Buffer " dba;
else
{
tb = blkres[sstate, "Buffer " dba];
tb = add_resource(tb, pid);
blkres[sstate, "Buffer " dba] = tb;
}
mode[sstate, pid, dba] = blmode;
in_buffer_so = ;
next; } # RESOURCE: Lock Element Dump
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# pre-9i Example:
# LOCK CONTEXT DUMP (address: 0x90ceab20):
# op: nmd: EXCLUSIVE dba: 0x5400004f cls: DATA cvt: cln:
# LOCK ELEMENT DUMP (number: , address: 0x91212498):
# mod: NULL rls:0x00 acq: inv: lch:0x921a366c,0x921a366c
# lcp: 0x90ceab20 lnk: 0x90ceab30,0x90ceab30 #
# Complete: Always assumes waiting AND just identifies one resource !!
#
#
# 9i Example:
# LOCK CONTEXT DUMP (address: 0x5f720b778):
# op: nmd: S tsn: rdba: 0xd300e0fb cls: DATA type:
# GLOBAL CACHE ELEMENT DUMP (address: 0x3f0fb07a0):
# id1: 0xd2c0e0fb id2: 0x8000 lock: SG rls: 0x000 acq: 0x01
# ^^
# this is actually two strings. kcllemode and kcllelocal. The first is the
# lock mode and the second a one letter code to denote a [G]lobal or [L]ocal
# lock. /LOCK CONTEXT DUMP/ { getline; sub(CR,""); isnull = ;
if ($ == "NULL" ||
(a9ienabled && $ == "N")) isnull = ;
wantmode = $;
getline; sub(CR,"");
if (a9ienabled)
tmp = "Elem " $;
else
tmp = "Elem " $;
if (!isnull)
waitres[sstate, pid] = tmp;
else
blkres[sstate, tmp] = pid;
if (!verbose) next;
getline; sub(CR,""); # For 9i+ just use the entire lock code even tho'
# it has a G or L appended to denote the lock scope
if (a9ienabled)
mode[sstate, pid, tmp] = $;
else
mode[sstate, pid, tmp] = $;
getline; getline; getline; getline;getline;getline;
sub(CR,"");
tb = objname[sstate, tmp] " ";
tb = tb $;
objname[sstate, tmp] = tb;
next } ##
## Verbose Processing
##
verbose != { next } # Handle to Object Mapping (Verbose mode)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example:
# LIBRARY OBJECT HANDLE: handle=40e25e08
# name=TEST.CRSMESSAGELOG
# hash=e2deff52 timestamp=-- ::
# namespace=TABL/PRCD flags=TIM/SML/[] /LIBRARY OBJECT HANDLE:/ { # next; # Just skip for now
handle=$; getline; sub(CR,"");
if (objname[sstate, handle]) next;
# Skip child cursors for now.
if ($ ~ "namespace=") next;
sub("^ *name=","");
if (!$) getline; sub(CR,"");
txt = $;
while ($ !~ "namespace") getline;
sub(CR,""); type=$;
sub("namespace=","",type);
objname[sstate, handle] = type ":" txt;
next } # v1.0.22: Handle new 11g format # Example:
# LIBRARY HANDLE:0x29472d38 bid= hid=351c2d7d lmd=S pmd=S sta=VALD
# name=TC.TEST
# hash=525f272508994441bd41310f351c2d7d idn=
# tim=-- :: kkkk-dddd-llll=--
# exc= ivc= ldc= cbb= rpr= kdp= slc= dbg=
# dmtx=0x29472d94(, , ) mtx=0x29472db8(, , )
# nsp=TABL() typ=TABL() llm= flg=KGHP/TIM/SML/[0200e800] /LIBRARY HANDLE:/ { sub("HANDLE:", "HANDLE: ");
handle=$; getline; sub(CR,"");
if (objname[sstate, handle]) next;
# Skip child cursors for now.
if ($ ~ "name=")
{
sub("^ *name=","");
if (!$) txt = "Unknown";
else txt = $;
while ($ !~ "nsp=") getline;
sub(CR,"");
type=$;
sub("nsp=","",type);
objname[sstate, handle] = type ":" txt;
}
} # New 12c format.
# Example:
# LibraryHandle: Address=0x16af064ed8 Hash=a2577acc LockMode=X PinMode=X LoadLockMode= Status=VALD
# ObjectName: Name=SCOTT.EMP
# FullHashValue=... Namespace=TABLE/PROCEDURE() Type=TABLE() ... /^ *LibraryHandle:/ { handle=$; sub("Address=", "", handle);
if (objname[sstate, handle]) next;
getline; sub(CR,"");
# Skip child cursors for now.
if ($ ~ "ObjectName:")
{
txt=$;
sub("Name=", "", txt);
if (!txt) txt = "Unknown";
while ($ !~ " Type=") getline;
sub(CR,"");
gsub("=", " ");
type=$;
if (NR > - && NR < +)
printf("type='%s'\n", type);
objname[sstate, handle] = type ":" txt;
}
} # END Processing
# ~~~~~~~~~~~~~~
# Ok - Let's put all the pieces together and you never know.....It just may
# make sense !!
#
END { printf("\nAss.Awk Version %s\n~~~~~~~~~~~~~~~~~~~~~~\n", version);
printf("Source file : %s\n", FILENAME);
if (kglstack) printf("\nKGL/KQR Stacks captured.\n"); if (!sstate)
{
printf("\nWARNING:\n~~~~~~~\n");
printf("The string \"SYSTEM STATE\" wasn't found in the file!!\n");
} for (i=; i<=sstate; i++)
{
if (ts12_2)
printf("\nSystem State %d\t(%s)\n%s\n", i, tstamp[i],
"~~~~~~~~~~~~~~\t ~~~~~~~~~~~~~~~~~~~~~~~~~~");
else
printf("\nSystem State %d\t(%s)\n%s\n", i, tstamp[i],
"~~~~~~~~~~~~~~\t ~~~~~~~~~~~~~~~~~~~~~~~");
if (pstate_seen[i])
{
printf("\nWARNING:\n~~~~~~~\n");
printf("The string \"PROCESS STATE\" was seen in the file and ");
printf("this can stop processing\nif seen -within- a ");
printf("systemstate.\n");
printf("* Highest PID seen across systemstate is %5d\n",
pstate_seen[i]);
printf("* Highest PID seen across file is %5d\n\n", hipid);
}
if (abort_seen[i])
{
printf("%s\n", abort_err);
al = split(ablist[i], abelem, " ");
for (abort_ind=; abort_ind <= al; abort_ind++)
printf(" Process %s at line %d\n", abelem[abort_ind],
aborted[abelem[abort_ind]]);
printf("\n");
}
blocking = "";
blkcnt = ; objcnt = ;
for (j=; j<=pidcnt[i]; j++)
{
pid = pidarray[i,j];
tmp = waitres[i, pid];
tmp1 = "";
if (tmp) tmp1 = "["tmp"]";
printf("%s %-35s%s%s %s\n", pid, wait_event[i,pid],tmp1,
isdead[i, pid]?" [DEAD]":"",seq[i, pid]);
if (wait_event[i,pid]) level_big_enuf[i] = ;
if (seqinfo && i > &&
sameseq(wait_event[i,pid], wait_event[i-,pid],
seq[i, pid], seq[i-, pid]) )
{
# printf("DBG> Process %s seq (%s)\n", pid, seq[i, pid]);
seq_stuck = seq_stuck?min(seq_stuck, j):j;
} pidchar = pid " "; # coerce
padlen = length(pidchar);
# We can't use C's "%.s" format mask so use hard-coded strings.
if (padlen >= )
padstr=padstrarr[];
else
padstr=padstrarr[padlen]; if (oct[i,pid] && oct[i,pid]!=)
{
if (cmdtab[oct[i,pid]]) printf("%sCmd: %s\n", padstr,
cmdtab[oct[i,pid]]);
else
printf("%sCmd: Unknown(%s)\n", padstr, oct[i,pid]);
}
if (fblk[i, pid])
printf("%sFinal Blocker: %s\n", padstr, fblk[i, pid]);
#
# Verbose: Need to describe wait_event details as well !!
# sub(" ", "_", tmp);
if (!index(blocking, tmp) && waitres[i,pid])
{
blocking = blocking " " tmp;
blklist[++blkcnt] = waitres[i,pid];
if (verbose)
{
objid[++objcnt] = waitres[i, pid];
} # end verbose
}
} # end j # if systemstate level seems to low then warn of this
if (!level_big_enuf[i])
warn_level();
#
# Summary of the blocking resources
#
if (blkcnt)
{
printf("\n");
printf("Blockers\n~~~~~~~~\n\n\t%s\n\t%s\n\t%s\n", tx1, tx2, tx3);
printf("\t%s\n\t%s\n\t%s\n\t%s\n", tx4, tx5, tx6, tx7);
printf("\t%s\n\t%s\n\t%s\n", tx8, tx9, tx10);
printf("\t%s\n\t%s\n\t%s\n\t%s\n\n", tx11, tx12, tx13, tx14);
printf("%28s %6s %s\n", "Resource", "Holder", "State");
}
else
printf("\nNO BLOCKING PROCESSES FOUND\n"); # v1.0.45: Build a list of pids that block for pid to sid mapping
pidmapcntr = ; for (k=; k<=blkcnt; k++)
{
pidlist = blkres[i, blklist[k]]; # Someone must be waiting for the resource if we got this far.
if (!pidlist) pidlist = UNKNOWN_PID; numpids = split(pidlist, tpid, " ");
for (z=; z<=numpids; z++)
{
printf("%28s %6s ", blklist[k], tpid[z]); if (tpid[z] != UNKNOWN_PID)
pidmap[++pidmapcntr] = tpid[z]; # -- Handle self deadlocks !!
if (!latches_seen && blklist[k] ~ "Latch")
latches_seen = ; if (waitres[i, tpid[z]])
{
# What if blker is multiple blockers ? Need to handle this case as well
# (and tidy code up [use functions?]). Currently just lists it in the following
# format :
# Enqueue TM-000008EC- : : is waiting for : :
#
blker = blkres[i, waitres[i, tpid[z]]]; # Don't know holder so let's print the resource
if (!sub("^ ", "", blker)) blker = waitres[i, tpid[z]]; # Prior to v1.0.26 if we had a self-deadlocked session then
# the output would list ALL the resources that the session
# held that blocked itself or others as being in a
# self-deadlock. We now test the resource so that *only* the
# resource that caused the self-deadlock is listed with the
# "self-deadlock" attribute.
if (tpid[z] == blker &&
blklist[k] == waitres[i, tpid[z]])
{
if (eqconv[i, tpid[z], waitres[i, tpid[z]]] == EQCNV)
printf("Enqueue conversion\n");
else
printf("Self-Deadlock\n");
}
else
printf("%s is waiting for %s\n", tpid[z], blker);
}
else if (wait_event[i, tpid[z]])
printf("%s\n", wait_event[i, tpid[z]]);
else
printf("Blocker\n");
} # end z
} # end k if (pidmapcntr)
{
printf("\nPID to SID Mapping\n");
printf( "~~~~~~~~~~~~~~~~~~\n");
for (pm=; pm<=pidmapcntr; pm++)
{
sidcnt = split(sidlist[i, pidmap[pm]], sidnum, " ");
#sercnt = split(serlist[i, pidmap[pm]], sernum, " ");
printf("Pid %d maps to Sid(s):", pidmap[pm]);
for (tt=; tt <= sidcnt; tt++)
printf(" %d", sidnum[tt]);
#printf("Sid %d(Ser %d) ", sidnum[tt], sernum[tt]);
printf("\n");
}
} # Processes with a PIN INSTANCE LOCK set with "resource=T" may
# block other processes as the pin cannot be granted until this
# setting is released. Since this is only seen under RAC just
# record that these have the -potential- to block other users
# across all nodes.
if (pinins[i])
{
printf("\n%s\n%s\n%s\n\n",pstr[],pstr[],pstr[]);
for (tt=; tt<=pinins[i]; tt++)
printf("%s%s\n", pinins_pid[i,tt],
pinins_pin[i, pinins_pid[i,tt]]);
} # end pinins if (latches_seen)
{
printf("\nSome of the above latches may be child latches. ");
printf("Please check the section\n");
printf("named 'Child Latch Report' below for further notes.\n");
} # v1.0.15 - alert the user of multiple session processes
if (msess[i] && !skipmsess)
{
printf("\nWarning: The following processes have multiple ");
printf("session state objects and\n");
printf("may not be properly represented above :\n");
msc = split(msess[i], ms, " ");
for (msi=; msi <= msc; msi += )
printf(" %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n",
ms[msi], ms[msi+], ms[msi+], ms[msi+], ms[msi+], ms[msi+],
ms[msi+], ms[msi+], ms[msi+], ms[msi+], ms[msi+],
ms[msi+], ms[msi+]);
} if (!verbose || !blkcnt) continue; printf("\nObject Names\n~~~~~~~~~~~~\n");
for (y=; y<=objcnt; y++)
{
tmp = objid[y];
sub("^PIN: ","", tmp);
sub("^LOCK: ","", tmp);
sub(" *.andle=","",tmp); # needed for 11g and 12c #printf("DBG> objname[%d, %s] = '%s'\n", i, tmp, objname[i,tmp]);
printf("%-25s\t%-30s\n", objid[y], substr(objname[i, tmp],,));
if (!child_latches && tmp ~ "Latch" && objname[i,tmp] ~ "Child")
child_latches = ;
} # End y
# Print out skipped branches
if (branchlst[i])
printf("\n%s\n%s\n%s\n%s\n%s\n", br1,br2,br3,br4, branchlst[i]); # If we see child latches then just make this fact obvious for now
# rather than trying to deduce the parent. The child and parent
# addresses will differ and this will not be properly detected by
# our blocker list.
if (latches_seen)
{
printf("\nChild Latch Report\n~~~~~~~~~~~~~~~~~~\n");
if (child_latches)
{
for (y=; y<CHILD_WARN; y++)
printf("%s\n", cw[y]); if (platch[i])
for (y=; y<platch[i]; y++)
printf(" %-4s %s\n", pl_pid[i, y], pl_str[i, y]);
else
printf(" No processes found.\n");
}
else
printf("No child latches seen.\n");
} # V1.0.33
if (wtrcount[i])
{
printf("\nLatch Wait List Information\n");
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); for (ww=; ww<= wtrcount[i]; ww++)
printf("%s\n", wtrstr[i, ww]); printf("\n%d %s seen.\n", wtrcount[i],
wtrcount[i] == ? "entry":"entries");
}
if (waitsummary)
{
printf("\nSummary of Wait Events Seen (count>%d)\n",
waitsummary_thresh);
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); wlc = split(waitlist[i], wl, " ");
wlseen = ;
for (wli=; wli <= wlc; wli++)
{
if (waitsum[i, wl[wli]] < waitsummary_thresh)
continue;
wlseen = ;
wltmp = wl[wli];
gsub("_", " ", wltmp);
printf("%6d : '%s'\n", waitsum[i, wl[wli]], wltmp);
}
if (!wlseen)
printf(" No wait events seen more than %d times\n",
waitsummary_thresh);
}
} # end i # Highlight processes that seem to be stuck
# Note that we do not care if it is stuck across ALL iterations
# of the systemstate dump - just across any TWO adjacent
# systemstates. This is because the user may have dumped the
# systemstate before the problem started, or killed the process.
#
# TODO: Remember that we may actually have a different OS process
# But unlikely to have the same seq# anyway
# Also, the wait_event string may actually comprise of more
# than just the wait event string itself. In some cases it
# also includes the p1,p2,p3 info as well.
if (seq_stuck)
{
printf("\nList of Processes That May Be Stuck");
printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
for (i=; i<=sstate; i++)
{
for (j=seq_stuck; j<=pidcnt[i]; j++)
{
pid = pidarray[i,j];
#printf("DBG: wait_event[%d,%s] = (%s)\n", i, pid,
#wait_event[i,pid]);
#printf("KDBG: seq[%d, %s] = %s\n", i, pid, seq[i, pid]);
if (wait_event[i, pid] ~ "waiting for" &&
sameseq(wait_event[i,pid], wait_event[i-,pid],
seq[i, pid], seq[i-, pid]) )
{
printf("%s %s %s\n", pid, wait_event[i,pid], seq[i,pid]);
## Stop duplicate printouts
seq[i,pid] = "";
} } # end for j
} # end for i
} # end seq_stuck printf("\n%*s%s\n", ((-length(TERM))-)/, " ", TERM);
printf("For the LATEST version of this utility see\n %s\n",
util_url);
printf("\nFor additional documentation see\n %s\n", doc_url);
printf("\nSuggested improvements, bugs etc. should be sent to %s\n",
emailid);
printf("\nEnd of report. %d Lines Processed.\n", NR); } # end END
使用ass来格式化systemstate的
Oracle下如何收集 Systemstate dump的更多相关文章
- Oracle systemstate dump介绍
当数据库出现严重的性能问题或者hang起的时候,那么我们非常需要通过systemstate dump来知道进程在做什么,在等待什么,谁是资源的持有者,谁阻塞了别人.在出现上述问题时,及时收集syste ...
- systemstate dump 介绍
systemstate dump 介绍 By Janezhang-Oracle on 十二月 13, 2012 当数据库出现严重的性能问题或者hang了的时候,我们非常需要通过systemstate ...
- 针对某个数据库error做systemstate dump
如果想对某个具体error做systemstate dump收集,可以借助event来实现. 例如想在数据库遇到ora-00054时,收集数据systemstate dump信息: 开启: sqlpl ...
- Oracle GI 日志收集工具 - TFA
1.TFA的目的: TFA是个11.2版本上推出的用来收集Grid Infrastructure/RAC环境下的诊断日志的工具,它可以用非常简单的命令协助用户收集RAC里的日志,以便进一步进行诊断:T ...
- Oracle ->> Oracle下实现SQL Server的TOP + APPLY
今晚很好奇想知道Oracle下有没有APPLY子句?如果有那怎么实现SQL Server下的TOP + APPLY.结果自己写了个例子. with a as ( order by grp_factor ...
- Oracle下的IF EXISTS()
妈蛋..作为一个使用了SQL SERVER有4 5年的程序猿,开始用Oracle真他妈不习惯.写法真他妈不一样.比如像写个像IF EXISTS(SELECT * FROM sys.tables WHE ...
- oracle下查询的sql已经超出IIS响应时间
场景: 最近一直发生oracle下查询的sql已经超出IIS响应时间,但是后台DB的SQL查询还未终止,一直在查询.这对DB是造成很大的压力. 解决办法 增加OracleCommand 中的Comma ...
- oracle下导出某用户所有表的方法
oracle下导出某用户所有表的方法 scott/tiger是用户名和密码,handson是导出的实例名 按用户方式导出数据(owner当中写的是用户名) exp scott/tiger@handso ...
- Oracle 下基于 DBMS_RESOURCE_MANAGER 包估算数据库存储 IO 性能
:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...
随机推荐
- sql 查找重复数据,并且重复数据有子集
SELECT A.* FROM comm_department A INNER JOIN ( select path,count(*) as count from comm_department gr ...
- maven项目跳转页面报空指针错误 Servlet.service() for servlet 异常
Servlet.service() for servlet jsp threw exceptionjava.lang.NullPointerExceptionat org.jaronsource.ms ...
- Flask&&人工智能AI --3
一.flask中的CBV 对比django中的CBV,我们来看一下flask中的CBV怎么实现? from flask import Flask, render_template, url_for, ...
- vbox 挂载共享文件时可能出现的问题以及对应的解决办法
VMBox挂载共享文件时可能出现的问题以及对应的解决办法 如果出现“未能加载虚拟光盘***.iso 到虚拟电脑的错误” : 左边一栏,右键光盘,eject,再安装
- Android中常用的几种加密
1.数字摘要 是指通过算法将长数据变为短数据,通常用来标识数据的唯一性,是否被修改,常用的加密算法有md5和sha1两种,如Android的App签名也是用的这两种算法. md5具有不可逆性,也可用来 ...
- 模拟虚拟的文件系统initrd/initramfs
请看initramfs文件的以下解析: [root@ant-colonies boot]# ls config--.el6.x86_64 lost+found efi symvers--.el6.x8 ...
- Jmeter-性能测试工具
0.概念和备注 //基本使用流程 测试计划-->右键 添加-> Threads(Users) --> 选择线程组 -->线程组-->右键 添加 --> Sample ...
- JDK动态代理详解-依赖接口
0. 原理分析 a). 自定义实现InvocationHandler类,实现代理类执行时的invoke方法 b). 使用Proxy.newProxyInstance生成接口的代理类(入参还包括Invo ...
- websocket的加密和解密
补充个小知识点:按位与运算 按位与运算是同位都为1才为1,有一个不为1就是0 websocket_hand import socket, base64, hashlib import websocke ...
- vue-extend 选项
vue-extend 选项 mixins 和extend 很相似,但有区别: var extendNews={ //后来的内容用变量接收 updated:function(){ console.log ...