Dissecting RAT Julian Dyke Independent Consultant 1 © 2012 - Julian Dyke juliandyke.com Introduction 2 Real Application Testing (RAT) Captures a workload in one environment Replays the workload in another environment Intended to provide assurance that performance will not degrade following an upgrade Success is dependent on: Use of Oracle features by the application Capture and replay procedures Separately licenced option Ensure your application is fully supported before purchasing licences © 2012 - Julian Dyke juliandyke.com Database Replay Production Client Client Test Client Replay Client Replay Client Application Tier Oracle Database Storage Storage Workload Capture 3 Oracle Database Storage Storage Workload Preprocessing © 2012 - Julian Dyke Storage Workload Replay Storage Analysis & Reporting juliandyke.com Prerequisites Workload capture is supported on the following versions: Version 4 One-off Patch 9.2.0.8 9373986 10.2.0.2 9373986 10.2.0.3 9373986 10.2.0.4 10239989 10.2.0.5 9373986 11.2.0.1 9373986 A one-off patch is required to implement workload capture in versions earlier than 11.2.0.2 Workload replay is supported in 11.2.0.1 and above Oracle 11.2.0.2 requires one-off patch 11870615 © 2012 - Julian Dyke juliandyke.com Patch 9373986 5 For 9.2.0.8 Solaris 64-bit includes lib libcommon9.a libgeneric9.a libpls9.a libserver9.a lib32 libcommon9.a libgeneric9.a libpls9.a rdbms lib kecwr.o kkxwtp.o ksms.o libknlopt.a kkxwtp.o rdbms admin dbmswrr.sql prvtwrr.plb catwrr.sql catwrrtb.sql catwrrtbc.sql catwrrvw.sql catwrrvwc.sql catnowrr.sql catnowrrc.sql © 2012 - Julian Dyke juliandyke.com Capture Directory Captured workload is stored in binary files in a directory tree below the capture directory Capture will stop if capture directory is full For RAC databases either: Use a shared file system for workload capture Use local file systems and subsequently merge contents For example: $ mkdir /home/oracle/capture1 $ chmod –R 777 /home/oracle/capture1 sqlplus ratuser/ratuser SQL> CREATE OR REPLACE DIRECTORY capture1 AS ‘/home/oracle/capture1’; 6 © 2012 - Julian Dyke juliandyke.com Capture Parameters In Oracle 10.2.0.5 and below, workload capture must be enabled using the PRE_11G_ENABLE_CAPTURE parameter In Oracle 10.2.0.5 and below: Workload capture can be enabled using : $ORACLE_HOME/rdbms/admin/wrrenbl.sql ALTER SYSTEM SET pre_11g_enable_capture=true SID=‘*’; Workload capture can be disabled using: $ORACLE_HOME/rdbms/admin/wrrdsbl.sql ALTER SYSTEM SET pre_11g_enable_capture=false SID=‘*’; 7 Workload capture is enabled by default in Oracle 11.2.0.1 and above The PRE_11G_ENABLE_CAPTURE parameter is not supported Workload capture can also be enabled using Enterprise Manager © 2012 - Julian Dyke juliandyke.com Capture Files One capture file is generated for each session Capture files have a .rec suffix For example: capfiles inst1 aa 8 wcr_czq44h0000003.rec wcr_czq45h0000004.rec wcr_czq45h0000005.rec wcr_czq45h0000006.rec wcr_czq45h0000007.rec wcr_czq45h0000008.rec wcr_czq45h0000009.rec Size is dependent on amount of activity in session © 2012 - Julian Dyke juliandyke.com Capture Files – Buffered I/O Capture files are written using buffered I/O Advantages are: Lower overhead Lower impact on workload Disadvantages are: Buffers are not flushed automatically SQL statements can be “lost” When capture ends or FINISH_CAPTURE is executed: Timeout period is specified Sessions will be informed during next database call If sessions make a database call within timeout period Capture file buffer will be flushed Otherwise contents will be lost 9 © 2012 - Julian Dyke juliandyke.com Getting Started 10 Use od utility to understand basic format ASCII Binary Hybrid If ASCII look for text strings od has several options including: Option Printable Non-Printable -a ASCII character Mnemonic -c ASCII character Octal or escape sequence -d Decimal Decimal -o Octal Octal -x Hexadecimal Hexadecimal © 2012 - Julian Dyke juliandyke.com Dumping ASCII characters + escapes od –c wcr_cvj2th0000001.rec 0000000 0000020 0000040 0000060 0000100 0000120 0000140 0000160 0000200 0000220 0000240 0000260 0000300 0000320 0000340 0000360 0000400 0000420 0000440 0000460 0000500 0000520 0000540 11 001 377 h a 1 F 8 \0 001 \0 C T 301 A 4 376 001 T \0 C < N > 005 315 e d 9 5 C B 017 \f 360 = 265 U 003 004 017 B \f 360 \v G \r 001 304 a o ' 3 0 376 002 002 O D 201 D S 301 002 = 005 O + U N 006 Y d w ) 0 9 004 001 ` 315 001 T S Y 265 \0 C ` 315 334 A L \n 200 e 200 D 3 301 B \0 304 017 = E S 201 \f 360 003 304 q G S 1 \0 r p 247 A 1 265 376 _ Y 002 271 S 5 T 004 O _ Y < E _ 1 \0 r 9 9 201 004 \0 001 \0 C $ 004 @ ` 315 s 001 001 ? T . \0 i o C E 001 T 301 B 017 \f 360 3 303 \r 003 304 B 024 026 \b E 2 001 n c 1 0 017 = 265 376 002 003 O \a 0 001 _ Y 376 : > A R © 2012 - Julian Dyke . \a f e B 4 002 006 201 004 001 ` 315 A 001 : s 001 004 004 \f M R 0 . 3 . 0 ) F i l e o . ( S Annoying s s =escape ' 3 6 characters 8 0 E A 3 6 5 0 5 \0 \f 001 ` \0 C 360 O 315 304 T = 031 001 017 301 265 201 T = B 376 004 301 265 \0 _ \0 B 376 304 Y 001 016 2 U D S E S @ 001 017 002 001 002 \0 ` 003 _ B 376 004 301 265 017 002 001 001 017 301 265 201 T S T E S T ; N L S _ L E R I C A I T O R Y \v h 5 0 A _ Y 002 # 201 004 \a $ B s 201 002 9 , A N ? juliandyke.com Dumping ASCII characters + mnemonics od –a wcr_cvj2th0000001.rec 0000000 0000020 0000040 0000060 0000100 0000120 0000140 0000160 0000200 0000220 0000240 0000260 0000300 0000320 0000340 0000360 0000400 0000420 0000440 0000460 0000500 0000520 0000540 12 soh enq soh ack nl 1 1 . del M D Y nul nul nul nul h e a d e r sp i a d o w sp p r o 1 9 ' ) nul ' sp C F 5 3 0 D A 9 E 8 C 0 9 3 1 9 soh nul B ~ eot A 5 soh T soh si stx soh B ~ eot A nul ff stx ` nul _ nul B C p O M D Y soh si T = D soh si stx nul ff A 5 soh T = 9 C p A U D S E S $ 3 4 etx S Y S 5 eot C ~ eot A 5 soh T @ cr soh si stx nul ff eot ` etx T B = C p O M D nul ff enq ` etx _ s B C p O M D Y soh dc4 < vt + \ q < soh syn N G U A G E ? bs > cr N L S _ T E 2 soh n c 1 0 si = 5 ~ stx etx O bel 0 soh _ Y ~ : > A R © 2012 - Julian Dyke . 0 . bel ) F f o . Annoying e s s B 6 8 mnemonics 4 3 6 stx nul ff ack C p soh T = eot A 5 soh B ~ ` nul _ M D Y A U D soh @ soh : stx nul s B ~ soh si stx eot A 5 eot T E ff N L M E R R I T 3 i sp = 0 5 soh O em soh eot nul soh S si ` eot soh soh S S I O . 0 vt l e sp ( S h ' 3 5 E A 0 0 5 A ` nul _ M D Y soh si stx T = # A 5 soh B ~ eot so 2 bel E S $ stx soh B etx _ s A 5 soh soh si stx T S 9 T ; , _ L A C A N R Y ? juliandyke.com Perl script to determine mnemonic values Write a Perl script to dump each character e.g. z.pl for ($i = 0;$i < 128;$i++) { printf ("%c",$i); } Use od –a to dump mnemonic values $ perl z.pl > zz $ od –a zz 0000000 nul soh stx etx eot enq ack bel bs 0000020 dle dc1 dc2 dc3 dc4 nak syn etb can 0000040 sp ! " # $ % & ' ( 0000060 0 1 2 3 4 5 6 7 8 0000100 @ A B C D E F G H 0000120 P Q R S T U V W X 0000140 ` a b c d e f g h 0000160 p q r s t u v w x 13 © 2012 - Julian Dyke ht nl vt em sub esc ) * + 9 : ; I J K Y Z [ i j k y z { ff fs , < L \ l | cr gs = M ] m } so si rs us . / > ? N O ^ _ n o ~ del juliandyke.com Perl script to filter od –a output filter.pl #!/usr/bin/perl use Switch; 14 while (<>) { chomp; @a = split (/\s+/,$_); $a = @a; for ($i = 1;$i < $a;$i++) { switch ($a[$i]) { case "nul" {$a[$i] = case "soh" {$a[$i] = case "stx" {$a[$i] = case "etx" {$a[$i] = ... } } printf ("%s",$a[$0]); for ($i = 1;$i < $a;$i++) { printf (" %3s",$a[$i]); } printf ("\n"); } © 2012 - Julian Dyke "00";} "01";} "02";} "03";} juliandyke.com od Utility od –a wcr_cvj2th0000001.rec | filter.pl 0000000 0000020 0000040 0000060 0000100 0000120 0000140 0000160 0000200 0000220 0000240 0000260 0000300 0000320 0000340 0000360 0000400 0000420 0000440 0000460 0000500 0000520 0000540 15 01 FF h a 1 F 8 00 01 00 C T A A 4 ~ 01 T 00 C < N > 05 M e d 9 5 C B 0F 0C p = 5 U 03 FE 0F B 0C p 0B G 0D 01 D a o ' 3 0 ~ 02 02 O D 01 D S A 02 = 05 O + U N 06 Y d w ) 0 9 FE 01 ` M 01 T S Y 5 00 C ` M \ A L 0A 00 e 20 00 D 3 A B 00 D 0F = E S 01 0C p 03 D q G S 1 00 r p ' A 1 5 ~ _ Y 02 9 S 5 T FE O _ Y < E _ 1 00 20 r 20 9 9 01 FE 00 01 00 C $ FE @ ` M s 01 01 ? T . 00 i o C E 01 T A B 0F 0C p 3 C 0D 03 D B 14 16 08 E 2 01 n c 1 0 0F = 5 ~ 02 03 O 07 0 01 _ Y ~ : > A R © 2012 - Julian Dyke . 07 f e B 4 02 06 01 FE 01 ` M A 01 : s 01 FE FE 0C M R 0 ) o s 6 3 00 C T A B 00 D U @ 02 B 0F A T N E I . F . s 8 6 0C p = 5 ~ _ Y D 01 00 ~ 02 5 E L R T 3 i 20 = 0 5 01 O 19 01 FE 00 01 S 0F ` FE 01 01 S S I O . l ( ' E 0 ` M 01 T A B 0E E 02 03 A 01 T T _ C R 0 e S 3 A 5 00 D 0F = 5 ~ 2 S 01 _ 5 0F S ; L A Y 0B 20 h 5 0 A _ Y 02 # 01 FE 07 $ B s 01 02 9 , A N ? juliandyke.com First string od –a wcr_cvj2th0000001.rec | filter.pl 0000000 0000020 0000040 0000060 0000100 0000120 0000140 0000160 0000200 0000220 0000240 0000260 0000300 0000320 0000340 0000360 0000400 0000420 0000440 0000460 0000500 0000520 0000540 16 01 FF h a 1 F 8 00 01 00 C T A A 4 ~ 01 T 00 C < N > 05 M e d 9 5 C B 0F 0C p = 5 U 03 FE 0F B 0C p 0B G 0D 01 D a o ' 3 0 ~ 02 02 O D 01 D S A 02 = 05 O + U N 06 Y d w ) 0 9 FE 01 ` M 01 T S Y 5 00 C ` M \ A L 0A 1 1 00 00 00 e r 20 20 p r 00 0x0A= ' 20 10 D A 9 3 1 9 A 5 01 B ~ FE 00 _ 00 D Y 01 0F 02 00 = 9 C E S $ S 5 FE 01 T @ 0C FE ` p O M 03 _ s D Y 01 q < 01 G E ? S _ T . 00 i o C E 01 T A B 0F 0C p 3 C 0D 03 D B 14 16 08 E 2 01 n c 1 0 0F = 5 ~ 02 03 O 07 0 01 _ Y ~ : > A R © 2012 - Julian Dyke . 07 f e B 4 02 06 01 FE 01 ` M A 01 : s 01 FE FE 0C M R 0 ) o s 6 3 00 C T A B 00 D U @ 02 B 0F A T N E I . F . s 8 6 0C p = 5 ~ _ Y D 01 00 ~ 02 5 E L R T 3 i 20 = 0 5 01 O 19 01 FE 00 01 S 0F ` FE 01 01 S S I O . l ( ' E 0 ` M 01 T A B 0E E 02 03 A 01 T T _ C R 0 e S 3 A 5 00 D 0F = 5 ~ 2 S 01 _ 5 0F S ; L A Y 0B 20 h 5 0 A _ Y 02 # 01 FE 07 $ B s 01 02 9 , A N ? juliandyke.com Second string 0000000 0000020 0000040 0000060 0000100 0000120 0000140 0000160 0000200 0000220 0000240 0000260 0000300 0000320 0000340 0000360 0000400 0000420 0000440 0000460 0000500 0000520 0000540 17 ) = 0x29 = 41 od –a wcr_cvj2th0000001.rec | filter.pl 01 FF h a 1 F 8 00 01 00 C T A A 4 ~ 01 T 00 C < N > 05 M e d 9 5 C B 0F 0C p = 5 U 03 FE 0F B 0C p 0B G 0D 01 D a o ' 3 0 ~ 02 02 O D 01 D S A 02 = 05 O + U N 06 Y d w ) 0 9 FE 01 ` M 01 T S Y 5 00 C ` M \ A L 0A 00 e 20 00 D 3 A B 00 D 0F = E S 01 0C p 03 D q G S 1 00 r p ' A 1 5 ~ _ Y 02 9 S 5 T FE O _ Y < E _ 1 00 20 r 20 9 9 01 FE 00 01 00 C $ FE @ ` M s 01 01 ? T . 00 i o C E 01 T A B 0F 0C p 3 C 0D 03 D B 14 16 08 E 2 01 n c 1 0 0F = 5 ~ 02 03 O 07 0 01 _ Y ~ : > A R © 2012 - Julian Dyke . 07 f e B 4 02 06 01 FE 01 ` M A 01 : s 01 FE FE 0C M R 0 ) o s 6 3 00 C T A B 00 D U @ 02 B 0F A T N E I . F . s 8 6 0C p = 5 ~ _ Y D 01 00 ~ 02 5 E L R T 3 i 20 = 0 5 01 O 19 01 FE 00 01 S 0F ` FE 01 01 S S I O . l ( ' E 0 ` M 01 T A B 0E E 02 03 A 01 T T _ C R 0 e S 3 A 5 00 D 0F = 5 ~ 2 S 01 _ 5 0F S ; L A Y 0B 20 h 5 0 A _ Y 02 # 01 FE 07 $ B s 01 02 9 , A N ? juliandyke.com String Attributes – Algorithm First attempt… The following C function uncompresses a string attribute int getstring (char *s) { int len = getch (); int i; for (i = 0; i < len;i++) { ch = getch (); s[i] = ch; } s[len] = 0; } 18 © 2012 - Julian Dyke juliandyke.com Numeric Attributes - Investigation 19 The simplest way to identify numbers is to generate multiple record files with differing known numeric values Good examples are: Error values e.g. 00942 (table or view does not exist) Row counts (can be controlled within table) Look for changes in the output file © 2012 - Julian Dyke juliandyke.com Numeric Attributes - Investigation 20 Some examples: Byte(s) Hexadecimal Decimal Length bits 0x01 0x1 1 00000000 (0x00) 0x02 0x2 2 00000000 (0x00) 0x7F 0x7F 127 00000000 (0x00) 0x80 0x80 0x80 128 10000000 (0x80) 0x80 0x81 0x81 129 10000000 (0x80) 0x80 0xFF 0xFF 255 10000000 (0x80) 0x81 0x00 0x100 256 10000000 (0x80) 0x81 0x01 0x101 257 10000000 (0x80) 0xC0 0xFF 0xFF 0xFFFF 65535 11000000 (0xC0) 0xC1 0x00 0x00 0x10000 65536 11000000 (0xC0) 0xE0 0xFF 0xFF 0xFF 0xFFFFFF 16777215 11100000 (0xE0) 0xE1 0x00 0x00 0x00 0x1000000 16777216 11100000 (0xE0) © 2012 - Julian Dyke juliandyke.com Numeric Attributes - Conclusions 21 Numbers are compressed The number of top bits set contiguously in first byte indicates number of bytes in number Remaining bits in first byte are part of number Maximum number of bits that can be set in length byte is 8 Maximum number of bytes in number is 8 Length bits always followed by zero bit EXCEPT when all 8 bits are set © 2012 - Julian Dyke juliandyke.com Numeric Attributes - Algorithm The following C function uncompresses an unsigned integer attribute between 1 and 8 bytes in length unsigned long getint () { ub8 n = getch (); ub8 res = 0; int i,j; int mask = 0xFF; for (i = 0;i < 8;i++) { mask = mask >> 1; if (((n << i) & 0x80) == 0) break; } res = n & mask; for (j = 0;j < i;j++) { res = (res << 8) | getch (); } return res; } 22 © 2012 - Julian Dyke juliandyke.com String Attributes – Second Attempt Second attempt now we understand numeric compression The following C function uncompresses a string attribute int getstring (char *s) { int len = getint (); int i; for (i = 0; i < len;i++) { ch = getch (); s[i] = ch; } s[len] = 0; } 23 © 2012 - Julian Dyke juliandyke.com SQL IDs 24 13 character representation of a 64-bit unsigned integer Uses a mapping of 32 characters to 0..31 Uses the characters 0-9 and a-z with the exception of e, i, l and o Used in Oracle 10.1 and above to identify SQL parent cursors 5-bit characters in SQL ID map to 8 bit characters in unsigned integer Right to left Top bit of left hand word is not used © 2012 - Julian Dyke juliandyke.com SQL ID Conversion 25 0 00000 h 10000 1 00001 j 10001 2 00010 k 10010 3 00011 m 10011 4 00100 n 10100 5 00101 p 10101 6 00110 q 10110 7 00111 r 10111 8 01000 s 11000 9 01001 t 11001 a 01010 u 11010 b 01011 v 11011 c 01100 w 11100 d 01101 x 11101 f 01110 y 11110 g 01111 z 11111 © 2012 - Julian Dyke juliandyke.com SQL IDs For example “cvj2th0000001“ = 0xcdc4598000000001 c v j 2 t h 0 0 0 0 0 0 1 01100 11011 10001 00010 11001 10000 00000 00000 00000 00000 00000 00000 00001 26 11001101 11000100 01011001 10000000 00000000 00000000 00000000 00000001 cd c4 59 80 00 00 00 01 © 2012 - Julian Dyke juliandyke.com SQL ID Conversion The following C function converts a 64-bit unsigned integer into a 13character SQL ID void ConvertLongToSQLID (unsigned long l,char *s) { char *map = "0123456789abcdfghjkmnpqrstuvwxyz"; int i; for (i = 0;i < 13;i++) { unsigned long k = (l >> (60 - i * 5)) & 0x1F; s[i] = map[k]; } s[13] = 0; } 27 © 2012 - Julian Dyke juliandyke.com SQL ID Conversion The following C function converts a 13-character SQL ID into a 64-bit unsigned integer void ConvertSQLIDToLong (char *s,unsigned long *l) { char *map = "0123456789abcdfghjkmnpqrstuvwxyz"; unsigned long res = 0; int i,j; for (i = 0;i < 13;i++) { for (j = 0;j < 32;j++) { if (s[i] == map[j]) break; } res = (res << 5) | j; } *l = res; } 28 © 2012 - Julian Dyke juliandyke.com Unix Time Unix (POSIX) time – time in seconds since the Epoch Not counting leap seconds Epoch was midnight on 1st January 1970 To determine current Unix time on Linux: #include <stdio.h> #include <sys/time.h> main () { struct timeval tv; struct timezone tz; gettimeofday (&tv,&tz); printf ("Seconds = %ld (0x%lx)\n",tv.tv_sec, tv.tv_sec); printf ("MicroSeconds = %ld (0x%lx)\n",tv.tv_usec,tv.tv_usec); } 29 © 2012 - Julian Dyke juliandyke.com Call Time Call time is based on Unix time Time in seconds since Unix epoch (midnight on 1st January 1970) The following C function uncompresses a call time attribute: void printCallTimeAttribute (char *name) { unsigned long l = getint (); unsigned long sec = l / 1000000; unsigned long usec = l % 1000000; time_t t = (time_t)sec; struct tm *tm = localtime (&t); printf (" %s = %04d-%02d-%02d %02d:%02d:%02d.%06d\n", name, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,usec); } 30 © 2012 - Julian Dyke juliandyke.com Audit Actions 31 Audit actions can be found in the SYS.AUDIT_ACTIONS table Name Type ACTION NUMBER NAME VARCHAR2(28) Common actions include: Action Name 1 CREATE TABLE 2 INSERT 3 SELECT 6 UPDATE 7 DELETE 9 CREATE INDEX 10 DROP INDEX 12 DROP TABLE 17 GRANT OBJECT 19 CREATE SYNONYM © 2012 - Julian Dyke juliandyke.com Actions Actions are Oracle DML and DDL statements char *getAction (unsigned int r) { switch (r) { case 1 : return ("CREATE TABLE"); case 2 : return ("INSERT"); case 3 : return ("SELECT"); case 6 : return ("UPDATE"); case 7 : return ("DELETE"); …. case 85 : return ("TRUNCATE TABLE"); case 157 : return ("CREATE DIRECTORY"); case 170 : return ("CALL METHOD"); case 189 : return ("MERGE STATEMENT"); } return ("UNKNOWN"); } 32 © 2012 - Julian Dyke juliandyke.com XML Format 33 Further analysis shows that record files have an XML-like format Code Description 0x01 <Section Number> Section (Element) 0x02 0x00 Begin Section 0x02 0x01 End Section 0x03 and above Attribute © 2012 - Julian Dyke juliandyke.com Workload Analyzer 34 Workload Analyzer Available in 11.2.0.2 and above Java program that analyses a workload capture directory Identifies parts of captured workload that may not replay accurately e.g. Insufficient data Errors occurring during workload capture Usage features not supported by Database Replay Results are stored in capture directory in the following files: wcr_cap_analysis.html wcr_cap_analysis.xml Requires : $ORACLE_HOME/jdbc/lib/dbranalyzer.jar $ORACLE_HOME/jdbc/lib/dbrparser.jar Java 1.5 or above © 2012 - Julian Dyke juliandyke.com Strings Utility Displays ASCII strings in a file: strings –n 3 $ORACLE_HOME/jdbc/lib/dbrparser.jar Where –n parameter specifies the minimum length of ASCII string to be printed. Default value is 4. For example: SECTION_INDICATOR CURSOR_NUMBER OCT HEADER_VERSION DB_VERSION HEADER_BLURP UID STMT_TEXT PGADEP FILE_ID CALL_COUNTER NROWS … 35 © 2012 - Julian Dyke juliandyke.com Elements 36 Code Description Code Description Code Description 2 PARSING_STMT 20 USER_LOGIN 50 PIGGYBACK_SECTION 4 BIND 21 SESSION_OP 51 START_CAPTURE 5 DEFINE 22 NLS_DATA 52 FINISH_CAPTURE 6 OUT_BIND 23 DLOGIN 53 FILTER 7 XCT_BEGIN 25 LOBOP 54 PROCESS_CAPTURE 8 XCT_END 27 LOBREAD 55 START_REPLAY 9 XCT_COMMIT_SCN 28 GETLOBLEN 56 FINISH_REPLAY 10 EXEC 36 LOBCHUNKSZ 57 USER_LOGOFF 11 FETCH 39 LOBFREETMP 58 ORFN_SECTION 12 PARSE 42 ERROR_SECTION 60 CONNECTION_REMAP 13 PARSE_ERROR 43 ERROR_LINE 65 DIV_LOG 14 SQ 44 MODACT_LINE 68 OBJ 15 USER_CALL 45 CURSOR_CLOSE 69 OBJID_READ 16 BINDS 46 CURSOR_CANCEL 70 OBJID_WRITE 17 OUTBINDS 47 CONNECTION_INFO 72 CUR_SCHEMA 18 DEFINES 48 RPC_SECTION 73 CLIENT_ID_LINE 19 EXEC_SECTION 49 RPC_LINE © 2012 - Julian Dyke juliandyke.com Attributes (1 of 4) 37 Code Description Code Description Code Description 3 CURSOR_NUMBER 20 FCH_EOF 39 TYPE_NAME 4 OCT 21 ITERATIONS 43 KENV_SCN 5 HEADER_VERSION 22 CURIT 44 DEP_SCN 6 DB_VERSION 23 TOTAL_BINDS 45 XID 7 HEADER_BLURP 24 BIND_POS 46 ROLLBACK 8 UID 25 BIND_BUFFER 47 READONLY 9 STMT_TEXT 27 PRIMARY_BIND_POS 48 POST_COMMIT_SCN 10 PGADEP 28 BINDVAR_NAME 49 PRE_COMMIT_SCN 11 FILE_ID 29 OACDTY 50 SQ_NAM 12 CALL_COUNTER 30 OACMXL 51 SQ_BNM 13 NROWS 31 OACMAL 52 SQ_BOW 14 FCH_REQ_ROWS 32 OACFLG 53 SQ_VAL 15 FCH_PRF_ROWS 33 OACCSI 54 SQ_FIRST 16 FCH_ORT 34 OACCSFRM 55 SQ_LAST 17 FE_FLAGS 36 INDICATOR 56 SQ_INCR 18 FCH_CURPOS 37 BNDDEF_FLAGS 57 SQ_COUNT 19 ERROR 38 SCHEMA_NAME 58 LOGIN_USER © 2012 - Julian Dyke juliandyke.com Attributes (2 of 4) 38 Code Description Code Description 59 SESSION_IDX 81 ERROR_COUNT 60 SESSION_SER 82 ERROR_INDEX 61 SESSION_OPC 83 ERROR_ARG 62 NLS_PNAME 84 MODULE 63 NLS_PVALUE 85 ACTION 64 NLS_CSID 86 CONN_STR 65 NLS_NCSID 87 RPC_OWNER 66 CALL_TIME 88 RPC_PACKAGE 67 CALL_WALLCLOCK 89 RPC_PROCNAME 68 DFILE_COUNTER 90 IS_RPC_FUNC 69 DFILE_NAME 91 RPC_PARACNT 70 DTL 92 RPC_PARAMODE 71 LOB_SRCLOC 93 RPC_PARATYPE 73 LOB_AMOUNT 95 ORFN_NUM 74 LOB_SRCOFFSET 96 ORFN_SEQ 76 LOB_OP 97 CAPTURE_NAME 77 LOB_FLAGS 98 CAPTURE_DBID © 2012 - Julian Dyke juliandyke.com Attributes (3 of 4) 39 Code Description Code Description 99 CAPTURE_DBNAME 116 FILTER_VALUE 100 CAPTURE_STATUS 117 REPLAY_PREPARE_TIME 101 CAPTURE_START_TIME 118 REPLAY_NUM_CLIENTS 102 CAPTURE_START_SCN 119 REPLAY_SYNC 103 CAPTURE_DEFAULT_ACT 120 REPLAY_CONN_TIME 104 CAPTURE_END_TIME 121 REPLAY_THINK_TIME_SCALE 105 CAPTURE_END_SCN 122 REPLAY_THINK_TIME_AUTO 106 CAPTURE_SIZE 123 REPLAY_NETWORK_TIME 107 CAPTURE_CONNECTS 124 REPLAY_THINK_TIME 108 CAPTURE_USER_CALLS 125 REPLAY_TIME_GAIN 109 CAPTURE_TRANSACTIONS 126 REPLAY_TIME_LOSS 110 CAPTURE_ERRORS 131 SQL_ID 111 CAPTURE_DBTIME 132 RPC_UEP 112 CAPTURE_ERROR_CODE 133 NOT_NULL 113 CAPTURE_ERROR_MSG 136 CAPTURE_DB_VERSION 114 FILTER_NAME 137 CAPTURE_DBPARALLEL 115 FILTER_ATTR 138 CAPTURE_DBTIME_T © 2012 - Julian Dyke juliandyke.com Attributes (4 of 4) 40 Code Description Code Description 139 CAPTURE_USER_CALLS_T 156 DIV_LOG_CALL_COUNTER 140 CAPTURE_USER_CALLS_E 157 DIV_LOG_SQL_ID 141 CAPTURE_TRANSACTIONS_T 158 DIV_LOG_SESSION_ID 142 CAPTURE_CONNECTS_T 159 DIV_LOG_SESSION_SERIAL 143 REMAP_CONN_ID 160 DIV_LOG_SERVICE 144 REMAP_CAPTURE_CONN 161 DIV_LOG_MODULE 145 REMAP_REPLAY_CONN 162 DIV_LOG_ACTION 146 DTLO 163 REPLAY_TIME_PAUSED 147 PP_ID 164 OBJECT_ID 148 DPATH_NAME 165 PLAN_HASH 149 DIV_LOG_TIME 166 CLIENT_ID 150 DIV_LOG_TYPE 167 WORKLOAD_ID 151 DIV_LOG_EXP_NUM_ROWS 168 REPLAY_DIR_NUM 152 DIV_LOG_OBS_NUM_ROWS 169 SELECT_FUP 153 DIV_LOG_EXP_ERROR 171 REPLAY_TYPE 154 DIV_LOG_OBS_ERROR 155 DIV_LOG_FILE_ID © 2012 - Julian Dyke juliandyke.com Headers REC files always include a header. For example: HEADER_VERSION = 1 DB_VERSION = 11.2.0.3.0 FILE_ID = cvj2th0000001 (0xcdc4598000000001) HEADER_BLURP = File header info. (Shadow process='3519') WORKLOAD_ID = C1B680EA0F530DA9E0436505A8C09319 The capture connect string is also recorded <CONNECTION_INFO> CONN_STR=(DESCRIPTION=(CONNECT_DATA=(SERVER=DEDICATED)(SE RVICE_NAME=TEST)(CID=(PROGRAM=java)(HOST=vm1.juliandyke.com)(USER =oracle)))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.5.101)(PORT=1521))) 41 © 2012 - Julian Dyke juliandyke.com SQL Statements Example of UPDATE statement <PARSE> CURSOR_NUMBER = 5 PGADEP = 0 OCT = UPDATE <EXEC_SECTION> OCT = UPDATE KENV_SCN = 1865384 <PARSING_STMT> CURSOR_NUMBER = 5 OCT = UPDATE PGADEP = 0 UID = 88 SQL_ID = 7uph2p0zpzwb8 (0x7d5602a83f5ff168) PLAN_HASH = 3311304765 <SQL> UPDATE car SET fastest_lap = :1 WHERE race_key = :2 AND driver_key = :3 </SQL> 42 © 2012 - Julian Dyke juliandyke.com SQL Statements Bind Variable #1 <BINDS> CURSOR_NUMBER = 5 ITERATIONS = 1 CURINT = 1 TOTAL_BINDS = 3 <BIND> BIND_POS = 0 BINDVAR_NAME = 1 OACDTY = 2 OACMXL = 21 OACMAL = 0 OACFLG = 3 OACCSI = 0 OACCSFRM = 0 BNDDEF_FLAGS = 32 BIND_BUFFER = Len 4 : 193 22 70 41 INDICATOR[1] = 0 INDICATOR[2] = 0 43 © 2012 - Julian Dyke juliandyke.com SQL Statements Affected objects <OBJ> CURSOR_NUMBER = 5 <OBJID_WRITE> OBJID = 77058 </OBJ> Execution statistics <EXEC> CURSOR_NUMBER = 5 NROWS = 1 PGADEP = 0 OCT = UPDATE ERROR = 0 ITERATIONS = 1 FE_FLAGS = 0 KENV_SCN = 1865384 DEP_SCN = 1865377 SELECT_FUP = 0 </EXEC> 44 © 2012 - Julian Dyke juliandyke.com Calls Within a session, every call is numbered <USER_CALL> CALL_COUNTER = 15 ORFN_SEQ = 14 ORFN_NUM = 14 CALL_TIME = 2012-06-06 21:27:01.339676 CALL_WALLCLOCK = 1339014420 45 Session number with call number can be used to identify divergences For each call REC file includes Call time (Timestamp) Wall clock time (Unix time) © 2012 - Julian Dyke juliandyke.com Fetches Every fetch is recorded separately For example – the DRIVER table contains 10 rows: SET ARRAYSIZE 4 SELECT driver_key, driver_name FROM driver; COMMIT; First fetch (1 row) <FETCH> CURSOR_NUMBER = 3 NROWS = 1 ERROR = 0 FCH_EOF = 0 FCH_REQ_ROWS = 0 FCH_ORT = 0 FE_FLAGS = 0 FCH_PRF_ROWS = 1 FCH_CURPOS = 0 46 © 2012 - Julian Dyke juliandyke.com Fetches Second fetch (4 rows) <FETCH> CURSOR_NUMBER = 3 NROWS = 4 etc.. Third fetch (4 rows) <FETCH> CURSOR_NUMBER = 3 NROWS = 4 etc.. Fourth fetch (1 row) <FETCH> CURSOR_NUMBER = 3 NROWS = 1 etc.. 47 Each fetch failure counts as a separate divergence © 2012 - Julian Dyke juliandyke.com Transactions Start of transaction <XCT_BEGIN> PGADEP = 0 XID = 1407417833227403 End of transaction <XCT_END> ROLLBACK = 0 READONLY = 0 PGADEP = 0 XID = 1407417833227403 KENV_SCN = 1865384 <XCT_COMMIT_SCN> PGADEP = 0 POST_COMMIT_SCN = 1865385 PRE_COMMIT_SCN = 1865384 XID = 1407417833227403 FE_FLAGS = 0 48 © 2012 - Julian Dyke juliandyke.com Sequences Sequence values are recorded in capture file. For example: <SQL> SELECT seq1.NEXTVAL FROM dual </SQL> <SQ> SQ_NAM = SEQ1 SQ_BNM = SEQ1 SQ_BOW = GP SQ_VAL = Len 2 : 193 11 </SQ> 49 Captured sequences values are probably used during replay to reduce divergence © 2012 - Julian Dyke juliandyke.com Errors Parse Errors are captured. For example SELECT COUNT(*) FROM t42; ORA-00942: table or view does not exist <PARSE_ERROR> ERROR = 942 <SQL> SELECT COUNT(*) FROM t42 </SQL> <ERROR_SECTION> ERROR_COUNT = 1 <ERROR_LINE> ERROR = 942 ERROR_INDEX = 1 </ERROR_LINE> </ERROR_SECTION> </PARSE_ERROR> 50 © 2012 - Julian Dyke juliandyke.com Errors Execution errors are also captured INSERT INTO t40 VALUES (1,42) ORA-00001: unique constraint (GP.SYS_C0012018) violated <EXEC> CURSOR_NUMBER = 3 NROWS = 0 PGADEP = 0 OCT = INSERT ERROR = 1 ITERATIONS = 1 FE_FLAGS = 0 KENV_SCN = 0 DEP_SCN = 3476879 SELECT_FUP = 0 </EXEC> 51 <ERROR_SECTION> ERROR_COUNT = 1 <ERROR_LINE> ERROR = 1 ERROR_INDEX = 1 ERROR_ARG = GP ERROR_ARG = SYS_C0012018 </ERROR_LINE> </ERROR_SECTION> © 2012 - Julian Dyke juliandyke.com PL/SQL Blocks PL/SQL blocks are captured in a similar way to PL/SQL statements. For example: <SQL> BEGIN INSERT INTO driver VALUES (‘SVET’,’Sebastian Vettel’); INSERT INTO driver VALUES (‘FALO’,’Fernando Alonso’); INSERT INTO driver VALUES (‘KRAI’,’Kimi Raikonnen’); END; </SQL> 52 HOWEVER individual statements executed by PL/SQL blocks are NOT captured Only top level error codes and rows returned are captured If PL/SQL subroutines change these may not be detected or reported © 2012 - Julian Dyke juliandyke.com Workload Metadata 53 Database capture generates workload metadata (WMD) files e.g. wcr_scapture.wmd wcr_fcapture.wmd Database replay generates workload metadata (WMD) files e.g. wcr_replay.wmd wcr_process.wmd All WMD files have the same format as REC files Elements and attributes vary but belong to same series © 2012 - Julian Dyke juliandyke.com Thank you for listening Any Questions? 54 © 2012 - Julian Dyke juliandyke.com