Professional Documents
Culture Documents
Jonathan Lewis and ORACLE_TRACE Oracle_Trace crashes my Database I start the SGA attach by searching every offset Anjo Kolk says James Morle wrote a program using x$ksmmem I show James my first draft using x$ksmmem James is baffled by why I'm hard coding offsets James says the offsets are in some X$ table I search, turn up a mail by Jonathan Lewison x$kqfco Goldmine all the offsets Thanks Mogens Nogard! Thanks to TomKyte's Decimal to Hex
http://oraperf.sourceforge.net
SGA on UNIX
SMON Snnn Dnnn Pnnn
PMON
Shared Pool
SGA
Database Buffer Cache
CKPT
Machine Memory
SGA on NT
Snnn SMON
Shared Pool Database Buffer Cache Redo Log Buffer
Dnnn
Pnnn
CKPT
Machine Memory
PMON
DBWR
LGWR
ARCH
oracle
Process Space
sqlplus
Fixed information
Data block cache SQL cache ( library cache/shared pool) Redo log buffer
Automatically
data blocks cached Log buffer Sql cache Updates of system and user statistics
User Queries
User info v$session System info v$parameter Performance statistics v$sysstat, v$latch, v$system_event Buffer cache headers, x$bh
Sort info on version 7 OPS locking info version 8 Contents of data blocks (only the headers or visible in X$)
Sampling User Waits, catch ephemeral data Scan LRU chain in X$bh Statistically approximate statistics SQL statistics per user
Low overhead
Statistical Sampling
By Rapidly Sampling SQL statistics and the users who have the statistics open, one can see how much work a particular user does with a particular SQL statement
Low Overhead
Marketing Appeal Clients are sensitive about their production databases Heisenberg uncertainty affect less overhead less affect monitoring has on performance which we are monitoring
Machine Memory
0x80000000
SGA
SGA
Buffer Cache
Graphic SGA
SGA
0x80000000
Fixed Area
Buffer Cache
Fixed Area
SGA
0x80000000
0x85251EF4
X$KSUSECST
170 Records
2328 bytes
Row 1 Row 3 Row 2
0x85251EF4
X$KSUSECST Record
One Record in X$KSUSECST
1276
2328 bytes
X$KSUSECST Fields
1276 Seq #
1278
Event #
1280 p1
1284 p2
1288 p3
struct foo { int id; int A; int B; int C; }; struct foo foo[N];
Struct C code
#include <stdio.h> #include <fcntl.h> #define N 20 /* structure definition: */
Struct Record
main(){ struct foo foo[20]; int fptr; /* zero out memory of struct */ memset(foo,0,sizeof(foo));
/* row 0 */
/* write to file, simulate SGA */ if ((fptr = open("foo.out",O_WRONLY | O_CREAT,0777)) < 0 ) return -1;
write(fptr,foo,sizeof(foo));
return 0; }
write(fp,foo,sizeof(foo));
ID 0 0 0 0 1 4 6 4 4
C 4 1 8 C 2 1 4
ID 6 8 1 2 4 0 1 1 6 0 2 2 0 4 Increasing 0 4
3 8 2 8 1 Memory address 0
Struct File Contents $ ./foo $ ls -l foo.out -rw-r--r-- joe dba 320 Feb 10 19:41 foo.out int = 32 bits Int = 4 bytes 20 entries * 4 int * 4 bytes/int = 320 bytes
od octal dump
$ od -l foo.out 1 0000000 2 0000020 0000040 0 * 0000500 12 22 0 13 23 0 13 24 0
Address is in Hex Column 2 is the ID Column 3 is field A Column 4 is field B Column 5 is field C
X$ tables ?
Ok, x$foo =~ foo[20] How do I get a list of x$ tables? Where is each X$ located? V$Fixed_Tables
Graphic: X$ Addresses
SGA
0x80000000
0x8???????? X$????
V$Fixed_Table
spool addr.sql select 'select 'addr, ||''''||name||''''||' from ' || name ||' where rownum < 2;' from v$fixed_table where name like 'X%' / spool off @addr.sql
X$ layout
6802B244 X$KSLEMAP 6802B7EC X$KSLEI 6820B758 X$KSURU 6820B758 X$KSUSE - v$session 6820B758 X$KSUSECST v$session_wait 6820B758 X$KSUSESTA v$session_stat 6820B758 X$KSUSIO 6826FBD0 X$KSMDD 6831EA0C X$KSRCHDL
V$Fixed_View_Definition
SQL> desc V$Fixed_View_Definition Name Type ----------------------------------- -------------VIEW_NAME VARCHAR2(30) VIEW_DEFINITION VARCHAR2(4000)
Definition of V$Session_Wait
SQL> select VIEW_DEFINITION from V$FIXED_VIEW_DEFINITION where view_name='GV$SESSION_WAIT'; VIEW_DEFINITION ----------------------------------------------------------------------select s.inst_id,s.indx,s.ksussseq,e.kslednam, e.ksledp1,s.ksussp1,s.ksussp1r,e. ksledp2, s.ksussp2,s.ksussp2r,e.ksledp3,s.ksussp3,s.ksussp3r, decode(s.ksusstim, 0,0,-1,-1,-2,-2, decode(round(s.ksusstim/10000),0,-1,round(s.ksusstim/10000))) , s.ksusewtm, decode(s.ksusstim, 0, 'WAITING', -2, 'WAITED UNKNOWN TIME', -1, ' WAITED SHORT TIME', 'WAITED KNOWN TIME') from x$ksusecst s, x$ksled e where bit and(s.ksspaflg,1)!=0 and bitand(s.ksuseflg,1)!=0 and s.ksussseq!=0 and s.ksussop c=e.indx
X$KQFTA
Kernel Query Fixed_view Table INDX use to find column information KQFTANAM X$ table names
X$KQFCO
Kernel Query Fixed_view Column KQFCOTAB Join with X$KQFTA.INDX KQFCONAM Column name KQFCOOFF Offset from beginning of the row KQFCOSIZ Columns size in bytes
X$KSUSECST Fields
1276 Seq #
1278
Event #
1280 p1
1284 p2
1288 p3
Address
BYTES
Buffer Redo Library Cache Buffer Cache Oracle provides access to some of the SGA contents via X$ tables
1) V$SESSION_WAIT Example
List of all users waiting Detailed information on the waits Data is ephemeral Useful in Bottleneck diagnostics High sampling rate candidate Event 10046 captures this info Good table for SGA sampling
V$SESSION_WAIT Description
SQL> desc v$session_wait Name ----------------------------------------SID SEQ# EVENT P1TEXT P1 P1RAW P2TEXT P2 P2RAW P3TEXT P3 P3RAW WAIT_TIME SECONDS_IN_WAIT STATE ) Type -------------------------,NUMBER ,NUMBER ,VARCHAR2(64) ,VARCHAR2(64) ,NUMBER ,RAW(4) ,VARCHAR2(64) ,NUMBER ,RAW(4) ,VARCHAR2(64) ,NUMBER ,RAW(4) ,NUMBER ,NUMBER ,VARCHAR2(19)
V$SESSION_WAIT Short
SQL> desc v$session_wait Name Type ---------------------------------------SID NUMBER SEQ# NUMBER EVENT VARCHAR2(64) P1 NUMBER P2 NUMBER P3 NUMBER)
V$FIXED_VIEW_DEFINITION Gives mappings of V$ views to X$ tables SQL> select VIEW_DEFINITION from V$FIXED_VIEW_DEFINITION where view_name='V$SESSION_WAIT;
Note: x$ksusecst. Ksussopc is the event # x$ksled.kslednam is a list of the event names where x$ksled.indx = x$ksusecst. ksussopc
3) V$ to X$ Field Mapping
Find the location of X$KSUSECST in the SGA SQL> select addr from x$ksusecst where rownum < 2 ADDR -------85251EF4
ROW_SIZE ---------------2328
Field Offsets
FIELD_NAME -----------------------------ADDR INDX KSUSEWTM INST_ID KSSPAFLG KSUSSSEQ KSUSSOPC KSUSSP1 KSUSSP1R KSUSSP2 KSUSSP2R KSUSSP3 KSUSSP3R KSUSSTIM KSUSENUM KSUSEFLG OFFSET ---------0 0 0 0 1 1276 1278 1280 1280 1284 1284 1288 1288 1292 1300 1308 SZ ---------4 4 4 4 1 2 2 4 4 4 4 4 4 4 2 4
Unexposed Fields
What happens between OFFSET 1 and 1276? Unexposed Fields Sometimes exposed elsewhere, in our case
V$SESSION V$SESSTAT
7) Offsets of Fields
Results X$KSUSECST
Machine Memory
0x80000000
SGA
SGA
Fixed Area
SGA
0x80000000
0x85251EF4
X$KSUSECST
170 Records
2328 bytes
Row 1 Row 3 Row 2
0x85251EF4
X$KSUSECST Record
One Record in X$KSUSECST
1276
2328 bytes
X$KSUSECST Fields
1276 Seq #
1278
Event #
1280 p1
1284 p2
1288 p3
);
shmid shared memory identifier specified shmaddr starting address of the shared memory shmflg - flags
The argument shmflg can be set to SHM_RDONLY . To avoid any possible data corruption the SGA should only be attached read only. The arguments shmid and shmaddr need to be set to Oracles SGA id and address.
The SGA attach call in C would be: Shmat(34401, 0x80000000, SHM_RDONLY); This call needs to be executed as a UNIX user who has read permission to the Oracle SGA
C Code Headers
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <errno.h> #include "event.h" event.h is for translating the event #s into event names
Events.h
Spool events.h select 'char event[][100]={' from dual; select '"'||name||'",' from v$event_name; select ' "" };' from dual; spool off
/* START ADDR of KSUSECST(V$SESSION_WAIT) */ #define KSUSECST_ADDR 0x85251EF4 /* NUMBER of ROWS/RECORDS in KSUSECST */ #define SESSIONS 150 /* SIZE in BYTES of a ROW in KSUSECST */ #define RECORD_SZ 2328
Set Up Variables
main(argc, argv) int argc; char **argv; { void *addr; int shmid; int shmaddr; void *current_addr; long p1r, p2r, p3r; unsigned int i, seq, tim, flg, evn;
Attach to SGA
/* ATTACH TO SGA */ shmid=atoi(argv[1]); shmaddr=SGA_BASE; if ( (void *)shmat( shmid, (void *)shmaddr, SHM_RDONLY) == (void *)-1 ) { printf("shmat: error attatching to SGA\n"); exit(); }
Output
$ sga_read_session_wait 34401 sid seq wait p1 0 40582 pmon timer 12C 1 40452 rdbms ipc message 12C 2 43248 rdbms ipc message 12C 3 24706 rdbms ipc message 12C 4 736 smon timer 12C 5 88 rdbms ipc message 2BF20 8 178 SQL*Net message from 6265710 p2 0 0 0 0 0 0 1 p3 0 0 0 0 0 0 0
Pitfalls
Byte Swapping 32 bit vs 64 bit Multiple Shared Memory Segments Segmented Memory Addresses are "unsigned int" Misaligned Access
Big Endian is "normal" , highest bit first In ascii, the word "byte" is stored as
echo 'byte' | od -x
y b e t 79 62 65 74
Byte Swap
Big Endian: 00 00 00 00 00 00 00 01 Little Endian 00 00 00 01 00 00 00 00 Solution, push the value over 8 places, to the right, ie >>8
64 bit vs 32 bit
SQL> desc x$ksmmem
Name ------------------------------------ADDR INDX INST_ID KSMMMVAL -> 32 bit Raw(8) -> 64 bit Type --------RAW(4) NUMBER NUMBER RAW(4)
Segmented Memory
x$ksuse can be dis-contiguous Work around: select 'int users[]={' from dual; select '0x'||addr||',' from x$ksuse; select '0x0};' from dual;
Misaligned Access
Some platforms seg fault when addressing misaligned bytes, need to read in even bytes or units of 4 bytes depending on platform
???
2328 bytes
v$session_wait v$session
1276
2328 bytes
x$ksusesta
x$ksusecst
x$ksuse
LRU HOT
LRU COLD