├── .gitignore ├── ERRATA.md ├── LICENSE ├── README.md └── code ├── bugs └── tracefile_identifier │ ├── 39079-traces │ ├── FREE_ora_39079.trc │ └── FREE_ora_39079_test01.trc │ ├── bug.pl │ └── bug.sql ├── experiments ├── adb │ ├── dev-trace-permissions.sql │ └── hello-world.sql ├── appinfo │ ├── test1.sql │ └── test2.sql ├── authid │ └── authid.sql ├── dbms_userdiag │ ├── 1-system.sql │ └── 2-dev2.sql ├── fetch-traces │ └── spool-trace-fetches.sql ├── hello-world │ └── hello-world.sql ├── oradebug │ └── tracefile_name.sql ├── trace-line-truncation │ └── t.sql ├── trace-size-estimate │ └── trace-size.sql └── triggers │ ├── trace-trigger.sql │ └── trace-user-machine-program.sql ├── scripts ├── GetTraceFile-setup.sql ├── GetTraceFile.java ├── GetTraceFile.pl ├── df-rate.pl ├── du-rate.pl ├── fill-disk.sh └── purge-traces.sh ├── sql ├── adb │ ├── my-trace-content.sql │ ├── trace-off.sql │ └── trace-on.sql ├── enabled-traces.sql ├── inventory.sh ├── login.sql ├── mr-packages │ ├── 1-owner.sql │ ├── 2-mrdev.sql │ ├── 3-mrdba.sql │ ├── 4-roles.sql │ ├── 5-tests.sql │ └── make.sql ├── my-handles.sql ├── my-trace-content.sql ├── my-trace-dir.sql ├── my-trace-file.sql ├── my-trace-status.sql ├── trace-off.sql ├── trace-on.sql ├── trace-script.sql ├── trace-username-off.sql ├── trace-username-on.sql └── your-trace-file.sql └── vim └── trc.vim /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /ERRATA.md: -------------------------------------------------------------------------------- 1 | TRACING ORACLE ERRATA 2 | === 3 | 4 | 8621: I found out by looking at an strace of a 19c sqltrace that Oracle no longer uses two write calls for each trace line. This invalidates statements on pages 32, 33, 48. 5 | 6 | 8622: Oracle writes STAT lines in segments. It takes between 3 and 5 write calls to write a STAT line. This invalidates statements made on pages 33, 48. 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Cary Millsap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tracing-oracle 2 | Code associated with Cary Millsap and Jeff Holt’s “Tracing Oracle” book project. 3 | -------------------------------------------------------------------------------- /code/bugs/tracefile_identifier/39079-traces/FREE_ora_39079.trc: -------------------------------------------------------------------------------- 1 | Trace file /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_39079.trc 2 | Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-Release 3 | Version 23.2.0.0.0 4 | Build label: RDBMS_23.2.0.0.0_LINUX.X64_230325 5 | ORACLE_HOME: /opt/oracle/product/23c/dbhomeFree 6 | System name: Linux 7 | Node name: localhost.localdomain 8 | Release: 5.15.0-8.91.4.1.el8uek.x86_64 9 | Version: #2 SMP Tue Mar 7 18:28:34 PST 2023 10 | Machine: x86_64 11 | VM name: KVM CPUID feature flags: 0x01000089 12 | CLID: P 13 | Instance name: FREE 14 | Redo thread mounted by this instance: 1 15 | Oracle process number: 69 16 | Unix process pid: 39079, NID: 4026531836, image: oracle@localhost.localdomain 17 | 18 | 19 | *** 2023-04-17T20:30:29.505342+00:00 (FREEPDB1(3)) 20 | *** SESSION ID:(302.35536) 2023-04-17T20:30:29.505362+00:00 21 | *** CLIENT ID:() 2023-04-17T20:30:29.505370+00:00 22 | *** SERVICE NAME:(freepdb1) 2023-04-17T20:30:29.505376+00:00 23 | *** MODULE NAME:(SQL Developer) 2023-04-17T20:30:29.505382+00:00 24 | *** ACTION NAME:() 2023-04-17T20:30:29.505388+00:00 25 | *** CLIENT DRIVER:(jdbcthin : 21.4.0.0.0) 2023-04-17T20:30:29.505393+00:00 26 | *** CONTAINER ID:(3) 2023-04-17T20:30:29.505399+00:00 27 | *** CLIENT IP:(10.0.2.2) 2023-04-17T20:30:29.505405+00:00 28 | *** CONNECTION ID:(fLaTMNmRQAeHR/9wKx0RJQ==) 2023-04-17T20:30:29.505411+00:00 29 | 30 | ===================== 31 | PARSING IN CURSOR #139752909124280 len=45 dep=0 uid=9 oct=47 lid=9 tim=98778560909 hv=2244691422 ad='64764978' sqlid='dt8t0g62wqjfy' 32 | BEGIN dbms_monitor.session_trace_enable; END; 33 | END OF STMT 34 | EXEC #139752909124280:c=0,e=1076,p=0,cr=29,cu=0,mis=1,r=1,dep=0,og=1,plh=0,tim=98778560907 35 | WAIT #139752909124280: nam='SQL*Net message to client' ela=9 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778561313 36 | WAIT #139752909124280: nam='SQL*Net message from client' ela=5448 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778566779 37 | CLOSE #139752909124280:c=15,e=15,dep=0,type=0,tim=98778566879 38 | ===================== 39 | PARSING IN CURSOR #139752909108128 len=76 dep=1 uid=0 oct=3 lid=0 tim=98778567450 hv=1052578227 ad='6e976648' sqlid='04kug40zbu4dm' 40 | select policy#, action# from aud_object_opt$ where object# = :1 and type = 2 41 | END OF STMT 42 | EXEC #139752909108128:c=49,e=49,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778567450 43 | FETCH #139752909108128:c=54,e=55,p=0,cr=14,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778567546 44 | STAT #139752909108128 id=1 cnt=0 pid=0 pos=1 obj=640 op='TABLE ACCESS FULL AUD_OBJECT_OPT$ (cr=14 pr=0 pw=0 str=1 time=55 dr=0 dw=0 us cost=5 size=114 card=1)' 45 | CLOSE #139752909108128:c=0,e=1,dep=1,type=3,tim=98778567602 46 | ===================== 47 | PARSING IN CURSOR #139752909102184 len=86 dep=1 uid=0 oct=3 lid=0 tim=98778567645 hv=706081451 ad='6e95cd48' sqlid='dkpbcdcp1bwpb' 48 | select policy#, action#, intcol# from sys.aud_objcol_opt$ where object# = :1 49 | END OF STMT 50 | EXEC #139752909102184:c=32,e=31,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778567644 51 | FETCH #139752909102184:c=1,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778567732 52 | STAT #139752909102184 id=1 cnt=0 pid=0 pos=1 obj=641 op='TABLE ACCESS FULL AUD_OBJCOL_OPT$ (cr=0 pr=0 pw=0 str=1 time=3 dr=0 dw=0 us cost=2 size=91 card=1)' 53 | CLOSE #139752909102184:c=1,e=0,dep=1,type=3,tim=98778567769 54 | EXEC #139752909108128:c=0,e=18,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=4006480256,tim=98778568169 55 | FETCH #139752909108128:c=0,e=38,p=0,cr=14,cu=0,mis=0,r=0,dep=2,og=4,plh=4006480256,tim=98778568224 56 | CLOSE #139752909108128:c=0,e=1,dep=2,type=3,tim=98778568242 57 | EXEC #139752909102184:c=0,e=19,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=2013599597,tim=98778568271 58 | FETCH #139752909102184:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=2013599597,tim=98778568282 59 | CLOSE #139752909102184:c=0,e=0,dep=2,type=3,tim=98778568292 60 | ===================== 61 | PARSING IN CURSOR #139752909080728 len=868 dep=2 uid=0 oct=3 lid=0 tim=98778569268 hv=3633507567 ad='6e970728' sqlid='121ffmrc95v7g' 62 | select i.obj#,i.ts#,i.file#,i.block#,i.intcols,i.type#,i.flags,i.property,i.pctfree$,i.initrans,i.maxtrans,i.blevel,i.leafcnt,i.distkey,i.lblkkey,i.dblkkey,i.clufac,i.cols,i.analyzetime,i.samplesize,i.dataobj#,nvl(i.degree,1),nvl(i.instances,1),i.rowcnt,mod(i.pctthres$,256),i.indmethod#,i.trunccnt,nvl(c.unicols,0),nvl(c.deferrable#+c.valid#,0),nvl(i.spare1,i.intcols),i.spare4,i.spare2,i.spare6,decode(i.pctthres$,null,null,mod(trunc(i.pctthres$/256),256)),nvl(i.evaledition#,1),nvl(i.unusablebefore#,0),nvl(i.unusablebeginning#,0), ist.cachedblk,ist.cachehit,ist.logicalread from ind$ i, ind_stats$ ist, (select enabled, min(intcols) unicols,min(to_number(bitand(defer,1))) deferrable#,min(to_number(bitand(defer,4))) valid# from cdef$ where obj#=:1 and enabled > 1 group by enabled) c where i.obj#=c.enabled(+) and i.obj# = ist.obj#(+) and i.bo#=:1 order by i.obj# 63 | END OF STMT 64 | PARSE #139752909080728:c=0,e=959,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,plh=2542797530,tim=98778569267 65 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=22 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778570088 66 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=9 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778570291 67 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=7 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778570506 68 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=9 Bytes=65536 where=2 p3=0 obj#=4294967295 tim=98778570679 69 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=6 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778570832 70 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=5 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778571023 71 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=14 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778571497 72 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=5 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778571609 73 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=8 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572046 74 | WAIT #139752909080728: nam='Allocate CGA memory from OS' ela=8 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572376 75 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=13 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572637 76 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=4 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572680 77 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572703 78 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572725 79 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572750 80 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572772 81 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572793 82 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572814 83 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778572843 84 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=10 Bytes=196608 where=2 p3=0 obj#=4294967295 tim=98778572928 85 | EXEC #139752909080728:c=0,e=3641,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,plh=2542797530,tim=98778572974 86 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=6 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778573049 87 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=4 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778573091 88 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=5 Bytes=131072 where=1 p3=0 obj#=4294967295 tim=98778573205 89 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=4 Bytes=131072 where=1 p3=0 obj#=4294967295 tim=98778573267 90 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=3 Bytes=131072 where=1 p3=0 obj#=4294967295 tim=98778573286 91 | WAIT #139752909080728: nam='Allocate UGA memory from OS' ela=4 Bytes=65536 where=1 p3=0 obj#=4294967295 tim=98778573314 92 | FETCH #139752909080728:c=0,e=490,p=0,cr=7,cu=0,mis=0,r=1,dep=2,og=4,plh=2542797530,tim=98778573478 93 | ===================== 94 | PARSING IN CURSOR #139752907965816 len=86 dep=2 uid=0 oct=3 lid=0 tim=98778573868 hv=2426120986 ad='6e9f0e50' sqlid='0gwaa0289rasu' 95 | select /*+ rule */ pos#,intcol#,col#,spare1,bo#,spare2,spare3 from icol$ where obj#=:1 96 | END OF STMT 97 | PARSE #139752907965816:c=0,e=349,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=3,plh=299250003,tim=98778573868 98 | EXEC #139752907965816:c=0,e=504,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=3,plh=299250003,tim=98778574430 99 | FETCH #139752907965816:c=0,e=44,p=0,cr=3,cu=0,mis=0,r=1,dep=2,og=3,plh=299250003,tim=98778574492 100 | FETCH #139752907965816:c=0,e=4,p=0,cr=1,cu=0,mis=0,r=0,dep=2,og=3,plh=299250003,tim=98778574514 101 | STAT #139752907965816 id=1 cnt=1 pid=0 pos=1 obj=20 op='TABLE ACCESS BY INDEX ROWID ICOL$ (cr=4 pr=0 pw=0 str=1 time=46 dr=0 dw=0 us)' 102 | STAT #139752907965816 id=2 cnt=1 pid=1 pos=1 obj=42 op='INDEX RANGE SCAN I_ICOL1 (cr=3 pr=0 pw=0 str=1 time=44 dr=0 dw=0 us)' 103 | CLOSE #139752907965816:c=0,e=0,dep=2,type=3,tim=98778574571 104 | FETCH #139752909080728:c=0,e=10,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=2542797530,tim=98778574591 105 | EXEC #139752907965816:c=0,e=11,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=3,plh=299250003,tim=98778574619 106 | FETCH #139752907965816:c=0,e=8,p=0,cr=3,cu=0,mis=0,r=1,dep=2,og=3,plh=299250003,tim=98778574637 107 | FETCH #139752907965816:c=0,e=4,p=0,cr=2,cu=0,mis=0,r=1,dep=2,og=3,plh=299250003,tim=98778574652 108 | FETCH #139752907965816:c=0,e=2,p=0,cr=1,cu=0,mis=0,r=0,dep=2,og=3,plh=299250003,tim=98778574662 109 | CLOSE #139752907965816:c=0,e=0,dep=2,type=3,tim=98778574680 110 | FETCH #139752909080728:c=0,e=9,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=2542797530,tim=98778574697 111 | STAT #139752909080728 id=1 cnt=2 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=7 pr=0 pw=0 str=1 time=497 dr=0 dw=0 us cost=6 size=372 card=2)' 112 | STAT #139752909080728 id=2 cnt=2 pid=1 pos=1 obj=0 op='HASH JOIN OUTER (cr=7 pr=0 pw=0 str=1 time=451 dr=0 dw=0 us cost=5 size=372 card=2)' 113 | STAT #139752909080728 id=3 cnt=2 pid=2 pos=1 obj=0 op='NESTED LOOPS OUTER (cr=4 pr=0 pw=0 str=1 time=88 dr=0 dw=0 us cost=2 size=286 card=2)' 114 | STAT #139752909080728 id=4 cnt=2 pid=3 pos=1 obj=19 op='TABLE ACCESS CLUSTER IND$ (cr=3 pr=0 pw=0 str=1 time=71 dr=0 dw=0 us cost=2 size=182 card=2)' 115 | STAT #139752909080728 id=5 cnt=1 pid=4 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=49 dr=0 dw=0 us cost=1 size=0 card=1)' 116 | STAT #139752909080728 id=6 cnt=0 pid=3 pos=2 obj=75 op='TABLE ACCESS BY INDEX ROWID IND_STATS$ (cr=1 pr=0 pw=0 str=2 time=13 dr=0 dw=0 us cost=0 size=52 card=1)' 117 | STAT #139752909080728 id=7 cnt=0 pid=6 pos=1 obj=76 op='INDEX UNIQUE SCAN I_IND_STATS$_OBJ# (cr=1 pr=0 pw=0 str=2 time=12 dr=0 dw=0 us cost=0 size=0 card=1)' 118 | STAT #139752909080728 id=8 cnt=0 pid=2 pos=2 obj=0 op='VIEW (cr=3 pr=0 pw=0 str=1 time=62 dr=0 dw=0 us cost=3 size=43 card=1)' 119 | STAT #139752909080728 id=9 cnt=0 pid=8 pos=1 obj=0 op='SORT GROUP BY (cr=3 pr=0 pw=0 str=1 time=61 dr=0 dw=0 us cost=3 size=15 card=1)' 120 | STAT #139752909080728 id=10 cnt=0 pid=9 pos=1 obj=31 op='TABLE ACCESS CLUSTER CDEF$ (cr=3 pr=0 pw=0 str=1 time=33 dr=0 dw=0 us cost=2 size=15 card=1)' 121 | STAT #139752909080728 id=11 cnt=1 pid=10 pos=1 obj=30 op='INDEX UNIQUE SCAN I_COBJ# (cr=2 pr=0 pw=0 str=1 time=7 dr=0 dw=0 us cost=1 size=0 card=1)' 122 | CLOSE #139752909080728:c=0,e=2,dep=2,type=3,tim=98778574929 123 | ===================== 124 | PARSING IN CURSOR #139752908097464 len=585 dep=2 uid=0 oct=3 lid=0 tim=98778575568 hv=3191600260 ad='6e9eca90' sqlid='g0t052az3rx44' 125 | select name,intcol#,segcol#,type#,length,nvl(precision#,0),decode(type#,2,nvl(scale,-127/*MAXSB1MINAL*/),178,scale,179,scale,180,scale,181,scale,182,scale,183,scale,231,scale,0),null$,fixedstorage,nvl(deflength,0),default$,rowid,col#,property, nvl(charsetid,0),nvl(charsetform,0),spare1,spare2,nvl(spare3,0), nvl(evaledition#,1),nvl(unusablebefore#,0),nvl(unusablebeginning#,0), case when (type# in (1,8,9,96,112)) then nvl(collid, 16382) else 0 end case, nvl(collintcol#,0), nvl(acdrrescol#, 0), nvl(spare7, 0), nvl(spare9, 0), nvl(spare10, 0) from col$ where obj#=:1 order by intcol# 126 | END OF STMT 127 | PARSE #139752908097464:c=0,e=621,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,plh=3765558045,tim=98778575567 128 | EXEC #139752908097464:c=0,e=1941,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,plh=3765558045,tim=98778577561 129 | FETCH #139752908097464:c=0,e=79,p=0,cr=3,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577690 130 | FETCH #139752908097464:c=0,e=5,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577736 131 | FETCH #139752908097464:c=0,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577752 132 | FETCH #139752908097464:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577766 133 | FETCH #139752908097464:c=0,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577788 134 | FETCH #139752908097464:c=0,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577803 135 | FETCH #139752908097464:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577816 136 | FETCH #139752908097464:c=0,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577830 137 | FETCH #139752908097464:c=0,e=9,p=0,cr=1,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577848 138 | FETCH #139752908097464:c=0,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=2,og=4,plh=3765558045,tim=98778577862 139 | FETCH #139752908097464:c=0,e=6,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=3765558045,tim=98778577878 140 | STAT #139752908097464 id=1 cnt=10 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=79 dr=0 dw=0 us cost=3 size=980 card=14)' 141 | STAT #139752908097464 id=2 cnt=10 pid=1 pos=1 obj=21 op='TABLE ACCESS CLUSTER COL$ (cr=3 pr=0 pw=0 str=1 time=44 dr=0 dw=0 us cost=2 size=980 card=14)' 142 | STAT #139752908097464 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=16 dr=0 dw=0 us cost=1 size=0 card=1)' 143 | CLOSE #139752908097464:c=0,e=3,dep=2,type=3,tim=98778577972 144 | ===================== 145 | PARSING IN CURSOR #139752909122344 len=108 dep=1 uid=0 oct=3 lid=0 tim=98778578233 hv=1293296274 ad='61da5f50' sqlid='7kaq4kd6jc8nk' 146 | select pname, enable_flag, ptxt, pcol, pfschma, ppname, pfname, stmt_type, powner# from fga$ where obj# = :1 147 | END OF STMT 148 | PARSE #139752909122344:c=0,e=10442,p=0,cr=50,cu=0,mis=1,r=0,dep=1,og=4,plh=3736732316,tim=98778578233 149 | EXEC #139752909122344:c=0,e=816,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=3736732316,tim=98778579102 150 | FETCH #139752909122344:c=3,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3736732316,tim=98778579378 151 | STAT #139752909122344 id=1 cnt=0 pid=0 pos=1 obj=705 op='TABLE ACCESS BY INDEX ROWID BATCHED FGA$ (cr=0 pr=0 pw=0 str=1 time=8 dr=0 dw=0 us cost=0 size=2384 card=1)' 152 | STAT #139752909122344 id=2 cnt=0 pid=1 pos=1 obj=707 op='INDEX RANGE SCAN I_FGAP (cr=0 pr=0 pw=0 str=0 time=0 dr=0 dw=0 us cost=0 size=0 card=1)' 153 | CLOSE #139752909122344:c=1,e=0,dep=1,type=3,tim=98778579456 154 | EXEC #139752908097464:c=57,e=57,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3765558045,tim=98778579545 155 | FETCH #139752908097464:c=90,e=90,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778579648 156 | FETCH #139752908097464:c=5,e=5,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778579675 157 | FETCH #139752908097464:c=4,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778579690 158 | FETCH #139752908097464:c=4,e=4,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778579704 159 | FETCH #139752908097464:c=4,e=4,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3765558045,tim=98778579718 160 | CLOSE #139752908097464:c=0,e=0,dep=1,type=3,tim=98778579735 161 | EXEC #139752909108128:c=13,e=13,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778580114 162 | FETCH #139752909108128:c=70,e=70,p=0,cr=14,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778580202 163 | CLOSE #139752909108128:c=0,e=0,dep=1,type=3,tim=98778580220 164 | EXEC #139752909102184:c=13,e=13,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778580257 165 | FETCH #139752909102184:c=2,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778580273 166 | CLOSE #139752909102184:c=1,e=1,dep=1,type=3,tim=98778580287 167 | EXEC #139752909108128:c=0,e=10,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=4006480256,tim=98778580486 168 | FETCH #139752909108128:c=0,e=43,p=0,cr=14,cu=0,mis=0,r=0,dep=2,og=4,plh=4006480256,tim=98778580543 169 | CLOSE #139752909108128:c=0,e=1,dep=2,type=3,tim=98778580559 170 | EXEC #139752909102184:c=0,e=8,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=2013599597,tim=98778580578 171 | FETCH #139752909102184:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=2013599597,tim=98778580599 172 | CLOSE #139752909102184:c=0,e=0,dep=2,type=3,tim=98778580613 173 | EXEC #139752909108128:c=0,e=10,p=0,cr=0,cu=0,mis=0,r=0,dep=3,og=4,plh=4006480256,tim=98778580771 174 | FETCH #139752909108128:c=0,e=57,p=0,cr=14,cu=0,mis=0,r=0,dep=3,og=4,plh=4006480256,tim=98778580858 175 | CLOSE #139752909108128:c=0,e=2,dep=3,type=3,tim=98778580882 176 | EXEC #139752909102184:c=0,e=11,p=0,cr=0,cu=0,mis=0,r=0,dep=3,og=4,plh=2013599597,tim=98778580905 177 | FETCH #139752909102184:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=3,og=4,plh=2013599597,tim=98778580916 178 | CLOSE #139752909102184:c=0,e=0,dep=3,type=3,tim=98778580926 179 | ===================== 180 | PARSING IN CURSOR #139752918697464 len=97 dep=3 uid=0 oct=3 lid=0 tim=98778581472 hv=791757000 ad='6e9d44e0' sqlid='87gaftwrm2h68' 181 | select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname from obj$ o where o.obj#=:1 182 | END OF STMT 183 | EXEC #139752918697464:c=0,e=20,p=0,cr=0,cu=0,mis=0,r=0,dep=3,og=4,plh=1072382624,tim=98778581471 184 | FETCH #139752918697464:c=0,e=32,p=0,cr=2,cu=0,mis=0,r=0,dep=3,og=4,plh=1072382624,tim=98778581542 185 | CLOSE #139752918697464:c=0,e=2,dep=3,type=3,tim=98778581558 186 | ===================== 187 | PARSING IN CURSOR #139752905994392 len=52 dep=2 uid=0 oct=3 lid=0 tim=98778582018 hv=2917030595 ad='67d33730' sqlid='4njga0qqxwqq3' 188 | SELECT inst_id, name, value, con_id FROM x$diag_info 189 | END OF STMT 190 | PARSE #139752905994392:c=0,e=1388,p=0,cr=19,cu=0,mis=1,r=0,dep=2,og=4,plh=1636480816,tim=98778582018 191 | CLOSE #139752905994392:c=0,e=4,dep=2,type=0,tim=98778582071 192 | EXEC #139752918697464:c=0,e=11,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=1072382624,tim=98778582511 193 | FETCH #139752918697464:c=0,e=10,p=0,cr=2,cu=0,mis=0,r=0,dep=2,og=4,plh=1072382624,tim=98778582539 194 | CLOSE #139752918697464:c=0,e=0,dep=2,type=3,tim=98778582553 195 | EXEC #139752918697464:c=0,e=8,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,plh=1072382624,tim=98778582590 196 | FETCH #139752918697464:c=0,e=5,p=0,cr=2,cu=0,mis=0,r=0,dep=2,og=4,plh=1072382624,tim=98778582605 197 | CLOSE #139752918697464:c=0,e=0,dep=2,type=3,tim=98778582615 198 | ===================== 199 | PARSING IN CURSOR #139752908032088 len=99 dep=1 uid=0 oct=3 lid=0 tim=98778583221 hv=489924305 ad='8455aee0' sqlid='f5hc6cwfm79qj' 200 | SELECT inst_id, name, value, con_id FROM gv$diag_info WHERE inst_id = USERENV('INSTANCE') 201 | END OF STMT 202 | PARSE #139752908032088:c=2821,e=2903,p=0,cr=41,cu=0,mis=1,r=0,dep=1,og=4,plh=1636480816,tim=98778583220 203 | CLOSE #139752908032088:c=3,e=3,dep=1,type=0,tim=98778583286 204 | ===================== 205 | PARSING IN CURSOR #139752909367664 len=316 dep=1 uid=0 oct=3 lid=0 tim=98778583670 hv=2851274006 ad='6e8d5490' sqlid='6h3cwmunz5z8q' 206 | select col#, grantee#, privilege#,max(mod(nvl(option$,0),2)), max(bitand(nvl(option$,0), 8) /8), max(bitand(nvl(option$,0), 16) /16), max(bitand(nvl(option$,0),64) /64), max(bitand(nvl(option$,0), 128) /128) from objauth$ where obj#=:1 and col# is not null group by privilege#, col#, grantee# order by col#, grantee# 207 | END OF STMT 208 | EXEC #139752909367664:c=16,e=16,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778583670 209 | FETCH #139752909367664:c=21,e=22,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778583728 210 | CLOSE #139752909367664:c=0,e=1,dep=1,type=3,tim=98778583744 211 | ===================== 212 | PARSING IN CURSOR #139752909353056 len=298 dep=1 uid=0 oct=3 lid=0 tim=98778583770 hv=3498487326 ad='6e8ce780' sqlid='a4n4ayr88dbhy' 213 | select grantee#,privilege#,nvl(col#,0),max(mod(nvl(option$,0),2)),max(bitand(nvl(option$,0), 8) /8), max(bitand(nvl(option$,0), 16) /16), max(bitand(nvl(option$,0),64) /64), max(bitand(nvl(option$,0), 128) /128) from objauth$ where obj#=:1 group by grantee#,privilege#,nvl(col#,0) order by grantee# 214 | END OF STMT 215 | EXEC #139752909353056:c=14,e=14,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778583770 216 | FETCH #139752909353056:c=67,e=67,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778583863 217 | FETCH #139752909353056:c=2,e=2,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778583879 218 | FETCH #139752909353056:c=1,e=1,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778583889 219 | FETCH #139752909353056:c=4,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778583908 220 | CLOSE #139752909353056:c=1,e=1,dep=1,type=3,tim=98778583923 221 | ===================== 222 | PARSING IN CURSOR #139752908031928 len=141 dep=1 uid=0 oct=3 lid=0 tim=98778584323 hv=793605046 ad='6e8c85c0' sqlid='7nuw4xwrnuwxq' 223 | select col#,intcol#,toid,version#,packed,intcols,intcol#s,flags, synobj#, nvl(typidcol#, 0) from coltype$ where obj#=:1 order by intcol# desc 224 | END OF STMT 225 | PARSE #139752908031928:c=66,e=382,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=1720483994,tim=98778584323 226 | EXEC #139752908031928:c=0,e=932,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=1720483994,tim=98778585312 227 | FETCH #139752908031928:c=0,e=22,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=1720483994,tim=98778585361 228 | STAT #139752908031928 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=27 dr=0 dw=0 us cost=3 size=188 card=4)' 229 | STAT #139752908031928 id=2 cnt=0 pid=1 pos=1 obj=116 op='TABLE ACCESS CLUSTER COLTYPE$ (cr=3 pr=0 pw=0 str=1 time=19 dr=0 dw=0 us cost=2 size=188 card=4)' 230 | STAT #139752908031928 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=10 dr=0 dw=0 us cost=1 size=0 card=1)' 231 | CLOSE #139752908031928:c=0,e=0,dep=1,type=3,tim=98778585444 232 | ===================== 233 | PARSING IN CURSOR #139752905302456 len=117 dep=1 uid=0 oct=3 lid=0 tim=98778585776 hv=3141366592 ad='6e8bec30' sqlid='9rfqm06xmuwu0' 234 | select intcol#, toid, version#, intcols, intcol#s, flags, synobj# from subcoltype$ where obj#=:1 order by intcol# asc 235 | END OF STMT 236 | PARSE #139752905302456:c=0,e=318,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=832500465,tim=98778585776 237 | EXEC #139752905302456:c=0,e=656,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=832500465,tim=98778586488 238 | FETCH #139752905302456:c=0,e=21,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=832500465,tim=98778586535 239 | STAT #139752905302456 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=25 dr=0 dw=0 us cost=3 size=432 card=12)' 240 | STAT #139752905302456 id=2 cnt=0 pid=1 pos=1 obj=119 op='TABLE ACCESS CLUSTER SUBCOLTYPE$ (cr=3 pr=0 pw=0 str=1 time=18 dr=0 dw=0 us cost=2 size=432 card=12)' 241 | STAT #139752905302456 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=10 dr=0 dw=0 us cost=1 size=0 card=1)' 242 | CLOSE #139752905302456:c=0,e=0,dep=1,type=3,tim=98778586616 243 | ===================== 244 | PARSING IN CURSOR #139752905275568 len=71 dep=1 uid=0 oct=3 lid=0 tim=98778586953 hv=2470471216 ad='6e8b6160' sqlid='f3g84j69n0tjh' 245 | select col#,intcol#,ntab# from ntab$ where obj#=:1 order by intcol# asc 246 | END OF STMT 247 | PARSE #139752905275568:c=0,e=323,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=914792125,tim=98778586952 248 | EXEC #139752905275568:c=0,e=642,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=914792125,tim=98778587650 249 | FETCH #139752905275568:c=0,e=15,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=914792125,tim=98778587691 250 | STAT #139752905275568 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=17 dr=0 dw=0 us cost=3 size=42 card=3)' 251 | STAT #139752905275568 id=2 cnt=0 pid=1 pos=1 obj=121 op='TABLE ACCESS CLUSTER NTAB$ (cr=3 pr=0 pw=0 str=1 time=12 dr=0 dw=0 us cost=2 size=42 card=3)' 252 | STAT #139752905275568 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=5 dr=0 dw=0 us cost=1 size=0 card=1)' 253 | CLOSE #139752905275568:c=0,e=2,dep=1,type=3,tim=98778587780 254 | ===================== 255 | PARSING IN CURSOR #139752907712888 len=201 dep=1 uid=0 oct=3 lid=0 tim=98778588160 hv=95387876 ad='6e8ad8f0' sqlid='8fkf44w2uz074' 256 | select l.col#, l.intcol#, l.lobj#, l.ind#, l.ts#, l.file#, l.block#, l.chunk, l.pctversion$, l.flags, l.property, l.retention, l.freepools, l.maxinl from lob$ l where l.obj# = :1 order by l.intcol# asc 257 | END OF STMT 258 | PARSE #139752907712888:c=0,e=369,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2819763574,tim=98778588160 259 | EXEC #139752907712888:c=0,e=932,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2819763574,tim=98778589141 260 | FETCH #139752907712888:c=0,e=13,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=2819763574,tim=98778589182 261 | STAT #139752907712888 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=17 dr=0 dw=0 us cost=3 size=108 card=2)' 262 | STAT #139752907712888 id=2 cnt=0 pid=1 pos=1 obj=113 op='TABLE ACCESS CLUSTER LOB$ (cr=3 pr=0 pw=0 str=1 time=11 dr=0 dw=0 us cost=2 size=108 card=2)' 263 | STAT #139752907712888 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=6 dr=0 dw=0 us cost=1 size=0 card=1)' 264 | CLOSE #139752907712888:c=0,e=4,dep=1,type=1,tim=98778589275 265 | ===================== 266 | PARSING IN CURSOR #139752907710800 len=90 dep=1 uid=0 oct=3 lid=0 tim=98778589627 hv=673844243 ad='6cff92a0' sqlid='9g485acn2n30m' 267 | select col#,intcol#,reftyp,stabid,expctoid from refcon$ where obj#=:1 order by intcol# asc 268 | END OF STMT 269 | PARSE #139752907710800:c=0,e=338,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2544153582,tim=98778589627 270 | EXEC #139752907710800:c=0,e=606,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2544153582,tim=98778590283 271 | FETCH #139752907710800:c=0,e=12,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=2544153582,tim=98778590322 272 | STAT #139752907710800 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=15 dr=0 dw=0 us cost=3 size=42 card=3)' 273 | STAT #139752907710800 id=2 cnt=0 pid=1 pos=1 obj=125 op='TABLE ACCESS CLUSTER REFCON$ (cr=3 pr=0 pw=0 str=1 time=10 dr=0 dw=0 us cost=2 size=42 card=3)' 274 | STAT #139752907710800 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=6 dr=0 dw=0 us cost=1 size=0 card=1)' 275 | CLOSE #139752907710800:c=0,e=2,dep=1,type=3,tim=98778590401 276 | ===================== 277 | PARSING IN CURSOR #139752907551824 len=86 dep=1 uid=0 oct=3 lid=0 tim=98778590706 hv=2195287067 ad='6cf91550' sqlid='32bhha21dkv0v' 278 | select col#,intcol#,charsetid,charsetform from col$ where obj#=:1 order by intcol# asc 279 | END OF STMT 280 | PARSE #139752907551824:c=0,e=291,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=3765558045,tim=98778590705 281 | EXEC #139752907551824:c=0,e=620,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=3765558045,tim=98778591375 282 | FETCH #139752907551824:c=0,e=20,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778591421 283 | FETCH #139752907551824:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778591437 284 | FETCH #139752907551824:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778591448 285 | FETCH #139752907551824:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778591456 286 | FETCH #139752907551824:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3765558045,tim=98778591467 287 | STAT #139752907551824 id=1 cnt=4 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=3 pr=0 pw=0 str=1 time=21 dr=0 dw=0 us cost=3 size=252 card=14)' 288 | STAT #139752907551824 id=2 cnt=4 pid=1 pos=1 obj=21 op='TABLE ACCESS CLUSTER COL$ (cr=3 pr=0 pw=0 str=1 time=14 dr=0 dw=0 us cost=2 size=252 card=14)' 289 | STAT #139752907551824 id=3 cnt=1 pid=2 pos=1 obj=3 op='INDEX UNIQUE SCAN I_OBJ# (cr=2 pr=0 pw=0 str=1 time=7 dr=0 dw=0 us cost=1 size=0 card=1)' 290 | CLOSE #139752907551824:c=0,e=1,dep=1,type=3,tim=98778591543 291 | ===================== 292 | PARSING IN CURSOR #139752907542088 len=119 dep=1 uid=0 oct=3 lid=0 tim=98778591879 hv=166324347 ad='6cf8b3a0' sqlid='0fr8zhn4ymu3v' 293 | select intcol#,type,flags,lobcol,objcol,extracol,schemaoid, elemnum from opqtype$ where obj# = :1 order by intcol# asc 294 | END OF STMT 295 | PARSE #139752907542088:c=0,e=322,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=1231101765,tim=98778591879 296 | EXEC #139752907542088:c=0,e=728,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=1231101765,tim=98778592661 297 | FETCH #139752907542088:c=0,e=36,p=0,cr=1,cu=0,mis=0,r=0,dep=1,og=4,plh=1231101765,tim=98778592723 298 | STAT #139752907542088 id=1 cnt=0 pid=0 pos=1 obj=128 op='TABLE ACCESS BY INDEX ROWID OPQTYPE$ (cr=1 pr=0 pw=0 str=1 time=36 dr=0 dw=0 us cost=2 size=25 card=1)' 299 | STAT #139752907542088 id=2 cnt=0 pid=1 pos=1 obj=129 op='INDEX RANGE SCAN I_OPQTYPE1 (cr=1 pr=0 pw=0 str=1 time=36 dr=0 dw=0 us cost=1 size=0 card=1)' 300 | CLOSE #139752907542088:c=0,e=2,dep=1,type=3,tim=98778592788 301 | EXEC #139752918697464:c=0,e=15,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593501 302 | FETCH #139752918697464:c=0,e=14,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593533 303 | CLOSE #139752918697464:c=0,e=1,dep=1,type=3,tim=98778593549 304 | EXEC #139752918697464:c=0,e=8,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593580 305 | FETCH #139752918697464:c=0,e=5,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593597 306 | CLOSE #139752918697464:c=0,e=0,dep=1,type=3,tim=98778593608 307 | EXEC #139752918697464:c=0,e=7,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593633 308 | FETCH #139752918697464:c=0,e=2,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778593644 309 | CLOSE #139752918697464:c=0,e=1,dep=1,type=3,tim=98778593655 310 | ===================== 311 | PARSING IN CURSOR #139752909110936 len=70 dep=0 uid=9 oct=3 lid=9 tim=98778593741 hv=3473215688 ad='69c77a70' sqlid='33np90g7ha468' 312 | select value trace1 from v$diag_info where name = 'Default Trace File' 313 | END OF STMT 314 | PARSE #139752909110936:c=16966,e=26818,p=0,cr=178,cu=0,mis=1,r=0,dep=0,og=1,plh=1636480816,tim=98778593740 315 | EXEC #139752909110936:c=0,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1636480816,tim=98778593807 316 | WAIT #139752909110936: nam='SQL*Net message to client' ela=12 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778593847 317 | FETCH #139752909110936:c=0,e=44,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1636480816,tim=98778593912 318 | STAT #139752909110936 id=1 cnt=1 pid=0 pos=1 obj=0 op='FIXED TABLE FULL X$DIAG_INFO (cr=0 pr=0 pw=0 str=1 time=63 dr=0 dw=0 us cost=0 size=50 card=1)' 319 | WAIT #139752909110936: nam='Free private memory to OS' ela=36 Bytes=458752 where=4 p3=0 obj#=4294967295 tim=98778594011 320 | WAIT #139752909110936: nam='SQL*Net message from client' ela=1947 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778595986 321 | EXEC #139752909108128:c=23,e=23,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778596432 322 | FETCH #139752909108128:c=51,e=51,p=0,cr=14,cu=0,mis=0,r=0,dep=1,og=4,plh=4006480256,tim=98778596502 323 | CLOSE #139752909108128:c=1,e=1,dep=1,type=3,tim=98778596521 324 | EXEC #139752909102184:c=22,e=22,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778596554 325 | FETCH #139752909102184:c=1,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2013599597,tim=98778596566 326 | CLOSE #139752909102184:c=0,e=0,dep=1,type=3,tim=98778596578 327 | EXEC #139752909080728:c=54,e=54,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2542797530,tim=98778596648 328 | FETCH #139752909080728:c=100,e=100,p=0,cr=3,cu=0,mis=0,r=0,dep=1,og=4,plh=2542797530,tim=98778596758 329 | CLOSE #139752909080728:c=0,e=0,dep=1,type=3,tim=98778596789 330 | EXEC #139752908097464:c=36,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3765558045,tim=98778596842 331 | FETCH #139752908097464:c=30,e=30,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,plh=3765558045,tim=98778596884 332 | FETCH #139752908097464:c=3,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3765558045,tim=98778596906 333 | CLOSE #139752908097464:c=0,e=0,dep=1,type=3,tim=98778596922 334 | EXEC #139752909367664:c=18,e=19,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778597019 335 | FETCH #139752909367664:c=0,e=17,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778597048 336 | CLOSE #139752909367664:c=0,e=0,dep=1,type=3,tim=98778597061 337 | EXEC #139752909353056:c=0,e=13,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778597085 338 | FETCH #139752909353056:c=0,e=55,p=0,cr=5,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778597148 339 | FETCH #139752909353056:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778597166 340 | FETCH #139752909353056:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778597176 341 | FETCH #139752909353056:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=4,plh=2968095032,tim=98778597185 342 | FETCH #139752909353056:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=2968095032,tim=98778597196 343 | CLOSE #139752909353056:c=0,e=1,dep=1,type=3,tim=98778597208 344 | ===================== 345 | PARSING IN CURSOR #139752909113080 len=21 dep=0 uid=9 oct=3 lid=9 tim=98778597680 hv=3556818377 ad='84395f20' sqlid='658001za01gf9' 346 | select USER from dual 347 | END OF STMT 348 | PARSE #139752909113080:c=986,e=1646,p=0,cr=42,cu=0,mis=1,r=0,dep=0,og=1,plh=1388734953,tim=98778597679 349 | EXEC #139752909113080:c=0,e=13,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=98778597729 350 | WAIT #139752909113080: nam='SQL*Net message to client' ela=9 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778597762 351 | FETCH #139752909113080:c=0,e=6,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1388734953,tim=98778597792 352 | STAT #139752909113080 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 str=1 time=2 dr=0 dw=0 us cost=2 size=0 card=1)' 353 | WAIT #139752909113080: nam='SQL*Net message from client' ela=6695 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778604536 354 | CLOSE #139752909113080:c=8,e=9,dep=0,type=0,tim=98778604629 355 | CLOSE #139752909110936:c=5,e=5,dep=0,type=0,tim=98778604657 356 | ===================== 357 | PARSING IN CURSOR #139752909113080 len=8 dep=0 uid=9 oct=3 lid=9 tim=98778604744 hv=3150668925 ad='64dcc860' sqlid='0y30pf6xwqt3x' 358 | select 1 359 | END OF STMT 360 | PARSE #139752909113080:c=63,e=63,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=98778604744 361 | EXEC #139752909113080:c=20,e=20,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=98778604798 362 | WAIT #139752909113080: nam='SQL*Net message to client' ela=11 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778604840 363 | FETCH #139752909113080:c=6,e=6,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1388734953,tim=98778604865 364 | STAT #139752909113080 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 str=1 time=2 dr=0 dw=0 us cost=2 size=0 card=1)' 365 | WAIT #139752909113080: nam='SQL*Net message from client' ela=6353 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778611271 366 | CLOSE #139752909113080:c=12,e=12,dep=0,type=1,tim=98778611383 367 | ===================== 368 | PARSING IN CURSOR #139752909111600 len=47 dep=0 uid=9 oct=42 lid=9 tim=98778611437 hv=1961468708 ad='0' sqlid='g9qcgg1ufm8t4' 369 | alter session set tracefile_identifier='test01' 370 | END OF STMT 371 | PARSE #139752909111600:c=26,e=26,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=0,tim=98778611437 372 | 373 | *** TRACE CONTINUES IN FILE /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_39079_test01.trc *** 374 | 375 | -------------------------------------------------------------------------------- /code/bugs/tracefile_identifier/39079-traces/FREE_ora_39079_test01.trc: -------------------------------------------------------------------------------- 1 | Trace file /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_39079_test01.trc 2 | Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-Release 3 | Version 23.2.0.0.0 4 | Build label: RDBMS_23.2.0.0.0_LINUX.X64_230325 5 | ORACLE_HOME: /opt/oracle/product/23c/dbhomeFree 6 | System name: Linux 7 | Node name: localhost.localdomain 8 | Release: 5.15.0-8.91.4.1.el8uek.x86_64 9 | Version: #2 SMP Tue Mar 7 18:28:34 PST 2023 10 | Machine: x86_64 11 | VM name: KVM CPUID feature flags: 0x01000089 12 | CLID: P 13 | Instance name: FREE 14 | Redo thread mounted by this instance: 1 15 | Oracle process number: 69 16 | Unix process pid: 39079, NID: 4026531836, image: oracle@localhost.localdomain 17 | 18 | 19 | *** 2023-04-17T20:30:29.555939+00:00 (FREEPDB1(3)) 20 | *** SESSION ID:(302.35536) 2023-04-17T20:30:29.555959+00:00 21 | *** CLIENT ID:() 2023-04-17T20:30:29.555967+00:00 22 | *** SERVICE NAME:(freepdb1) 2023-04-17T20:30:29.555973+00:00 23 | *** MODULE NAME:(SQL Developer) 2023-04-17T20:30:29.555979+00:00 24 | *** ACTION NAME:() 2023-04-17T20:30:29.555985+00:00 25 | *** CLIENT DRIVER:(jdbcthin : 21.4.0.0.0) 2023-04-17T20:30:29.555990+00:00 26 | *** CONTAINER ID:(3) 2023-04-17T20:30:29.555996+00:00 27 | *** CLIENT IP:(10.0.2.2) 2023-04-17T20:30:29.556003+00:00 28 | *** CONNECTION ID:(fLaTMNmRQAeHR/9wKx0RJQ==) 2023-04-17T20:30:29.556010+00:00 29 | 30 | 31 | *** TRACE CONTINUED FROM FILE /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_39079.trc *** 32 | 33 | EXEC #139752909111600:c=44,e=44,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=0,tim=98778611515 34 | WAIT #139752909111600: nam='SQL*Net message to client' ela=11 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778611842 35 | WAIT #139752909111600: nam='SQL*Net message from client' ela=5419 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778617278 36 | CLOSE #139752909111600:c=8,e=8,dep=0,type=1,tim=98778617376 37 | EXEC #139752918697464:c=0,e=17,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619075 38 | FETCH #139752918697464:c=0,e=11,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619115 39 | CLOSE #139752918697464:c=0,e=1,dep=1,type=3,tim=98778619133 40 | EXEC #139752918697464:c=0,e=8,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619159 41 | FETCH #139752918697464:c=0,e=5,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619174 42 | CLOSE #139752918697464:c=0,e=0,dep=1,type=3,tim=98778619185 43 | EXEC #139752918697464:c=0,e=7,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619206 44 | FETCH #139752918697464:c=0,e=3,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,plh=1072382624,tim=98778619217 45 | CLOSE #139752918697464:c=0,e=1,dep=1,type=3,tim=98778619231 46 | ===================== 47 | PARSING IN CURSOR #139752905996888 len=70 dep=0 uid=9 oct=3 lid=9 tim=98778619336 hv=185555460 ad='6181f500' sqlid='7xynx405hyqh4' 48 | select value trace2 from v$diag_info where name = 'Default Trace File' 49 | END OF STMT 50 | PARSE #139752905996888:c=761,e=1933,p=0,cr=15,cu=0,mis=1,r=0,dep=0,og=1,plh=1636480816,tim=98778619336 51 | EXEC #139752905996888:c=0,e=43,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1636480816,tim=98778619411 52 | WAIT #139752905996888: nam='SQL*Net message to client' ela=14 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778619461 53 | FETCH #139752905996888:c=0,e=34,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1636480816,tim=98778619515 54 | STAT #139752905996888 id=1 cnt=1 pid=0 pos=1 obj=0 op='FIXED TABLE FULL X$DIAG_INFO (cr=0 pr=0 pw=0 str=1 time=60 dr=0 dw=0 us cost=0 size=50 card=1)' 55 | WAIT #139752905996888: nam='SQL*Net message from client' ela=7196 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778626777 56 | CLOSE #139752905996888:c=9,e=8,dep=0,type=0,tim=98778626877 57 | PARSE #139752909113080:c=20,e=21,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=98778626935 58 | EXEC #139752909113080:c=21,e=21,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=98778626971 59 | WAIT #139752909113080: nam='SQL*Net message to client' ela=10 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778627011 60 | FETCH #139752909113080:c=5,e=5,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1388734953,tim=98778627035 61 | WAIT #139752909113080: nam='SQL*Net message from client' ela=12672 driver id=1413697536 #bytes=1 p3=0 obj#=4294967295 tim=98778639733 62 | CLOSE #139752909113080:c=12,e=12,dep=0,type=3,tim=98778639887 63 | ===================== 64 | PARSING IN CURSOR #139752905996888 len=46 dep=0 uid=9 oct=47 lid=9 tim=98778641221 hv=2585690420 ad='619958d0' sqlid='7wwcby6d1x09n' 65 | BEGIN dbms_monitor.session_trace_disable; END; 66 | END OF STMT 67 | PARSE #139752905996888:c=1097,e=1277,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=98778641220 68 | EXEC #139752905996888:c=291,e=291,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=98778641582 69 | -------------------------------------------------------------------------------- /code/bugs/tracefile_identifier/bug.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use File::Basename; 6 | use experimental qw(switch); 7 | use Getopt::Long; 8 | 9 | our $Program = fileparse $0, qr(\..*); 10 | 11 | our %Opt = ( 12 | verbose => 0, 13 | ); 14 | our %Options = ( 15 | "help|?" => sub { print "Usage: $Program [--verbose] file ...\n"; exit; }, 16 | "verbose!" => \$Opt{verbose}, 17 | ); 18 | GetOptions(%Options) or die; 19 | 20 | my $filename; 21 | my %pic = (); # $pic{$c} is the line number where cursor ID $c is defined. 22 | 23 | FILE: while ($filename = shift @ARGV) { 24 | my $F; 25 | open($F, $filename) or do { 26 | warn "$main::Program: can't open '$filename' ($!)\n"; 27 | next; 28 | }; 29 | while (my $line = <$F>) { 30 | given ($line) { 31 | when (/^(PARSING IN CURSOR) \#([0-9]+)/) { 32 | my $cursor_id = $2; 33 | printf "%8d PIC #%s\n", $., $cursor_id if $Opt{verbose}; 34 | $pic{$cursor_id} = $.; 35 | } 36 | when (/^(PARSE|EXEC|FETCH|UNMAP|SORT UNMAP) \#([0-9]+)/) { # Leave out WAIT, CLOSE. 37 | my ($call, $cursor_id) = ($1, $2); 38 | printf "%8d \t%s #%s ", $., $call, $cursor_id if $Opt{verbose}; 39 | if ($pic{$cursor_id}) { 40 | printf "found PIC on line $pic{$cursor_id}\n" if $Opt{verbose}; 41 | } else { 42 | print "FAIL $filename:$. no definition for $cursor_id\n"; 43 | next FILE; 44 | } 45 | } 46 | } 47 | } 48 | print "OK $filename\n"; 49 | } 50 | 51 | 52 | __DATA__ 53 | 54 | Hello 55 | 56 | 57 | -------------------------------------------------------------------------------- /code/bugs/tracefile_identifier/bug.sql: -------------------------------------------------------------------------------- 1 | -- TRACEFILE_IDENTIFIER behavior SR 3-32741539641 2 | 3 | /* 4 | 5 | Setting TRACEFILE_IDENTIFIER leaves information out of the trace file 6 | 7 | When you set TRACEFILE_IDENTIFIER, the Oracle kernel process closes the 8 | existing trace file and opens a new one. The new file doesn't contain all of 9 | the information that it should. Specifically, it will not contain some 10 | "PARSING IN CURSOR" sections that have been written to the first of the two 11 | trace files. Impact is that, when we look at the trace file whose name has 12 | the new tracefile identifier in it, we can't determine the SQL or PL/SQL 13 | associated with all the cursors reported on in the trace. The workaround is 14 | to simply never use TRACEFILE_IDENTIFIER. This has been a problem since at 15 | least Oracle 10g, and it's still reproducible in 23c FREE. 16 | 17 | */ 18 | 19 | 20 | connect system/oracle 21 | alter session set max_dump_file_size=unlimited; 22 | 23 | exec dbms_monitor.session_trace_enable 24 | select value trace0 from v$diag_info where name = 'Default Trace File'; 25 | select 1; 26 | alter session set tracefile_identifier='1'; 27 | select value trace1 from v$diag_info where name = 'Default Trace File'; 28 | select 1; -- Must be the same statement as above. 29 | alter session set tracefile_identifier='2'; 30 | select value trace2 from v$diag_info where name = 'Default Trace File'; 31 | select 1; -- Must be the same statement as above. 32 | exec dbms_monitor.session_trace_disable 33 | 34 | /* 35 | 36 | Now, look in the two trace files. 37 | 38 | In my (cvm) tests, both TRACE1 and TRACE2 contained a 'PARSING IN CURSOR' 39 | section for the 'select 1' cursor. But run the test again. This time, the 40 | behavior is different: 41 | 42 | - In TRACE1, you'll see a 'PARSING IN CURSOR' section for the 'select 1' cursor. 43 | 44 | - In TRACE2, there is no 'PARSING IN CURSOR' section for the cursor. 45 | 46 | It appears that the DBMS is checking a state variable holding the information, 47 | "Have I emitted a 'PARSING IN CURSOR' section for this cursor?" The real 48 | information needs to be "Have I emitted a 'PARSING IN CURSOR' section for this 49 | cursor SINCE OPENING THE CURRENT TRACE FILE?" 50 | 51 | The impact of this behavior is: 52 | 53 | 1. People like the TRACEFILE_IDENTIFIER feature because it makes it easier to 54 | find their trace file in the trace directory. But the trace file created after 55 | a TRACEFILE_IDENTIFIER change is deficient in that it does not contain the SQL 56 | or PL/SQL associated with all the dbcalls in the trace. 57 | 58 | 3. The easiest workaround is to simply never use TRACEFILE_IDENTIFIER. That is 59 | my recommendation to people. It seems like a nice-to-have feature, but it's so 60 | easy these days to find the name of your trace file in V$DIAG_INFO that we 61 | recommend using that instead of TRACEFILE_IDENTIFIER. 62 | 63 | 4. A harder workaround (NOBODY will want to do this [or even know how]) is to 64 | always save both the "before" (TRACE1 in this example) and "after" (TRACE2 in 65 | this example) files, and then do sophisticated trace file surgery in an 66 | editor (being extremely careful with the tim values!), to provide the "PARSING 67 | IN CURSOR" information to any user of the "after" trace file. 68 | 69 | */ 70 | 71 | -------------------------------------------------------------------------------- /code/experiments/adb/dev-trace-permissions.sql: -------------------------------------------------------------------------------- 1 | -- demonstrate the permissions a developer needs for tracing (ADB-S) 2 | 3 | -- You must be ADMIN to perform the required grants. 4 | 5 | -- connect admin 6 | 7 | drop user dev1 cascade; -- Fresh start 8 | grant connect to dev1 identified by "Your-password-g0es-here"; 9 | grant create session to dev1; 10 | 11 | grant read on session_cloud_trace to dev1; -- Required to read trace file content 12 | grant alter session to dev1; -- Required to enable and disable tracing 13 | 14 | -- Connect for testing... 15 | connect dev1/Your-password-g0es-here 16 | 17 | -- Ensure that the required views are accessible 18 | desc session_cloud_trace 19 | 20 | -- Full cycle: trace an application and access its content. 21 | @adb/trace-on 22 | select 'hello, from ADB' from dual; 23 | @adb/trace-off 24 | @adb/my-trace-content 25 | 26 | -------------------------------------------------------------------------------- /code/experiments/adb/hello-world.sql: -------------------------------------------------------------------------------- 1 | -- "hello, world", your first trace (ADB-S) 2 | 3 | -- This script will ONLY run on an Oracle Autonomous Database on shared 4 | -- infrastructure system. 5 | 6 | -- See adb/dev-trace-permissions.sql for information about required privileges 7 | -- if you can't connect as ADMIN. 8 | 9 | -- connect admin 10 | 11 | @adb/trace-on 12 | select 'hello, world' from dual; 13 | @adb/trace-off 14 | @adb/my-trace-content 15 | 16 | -------------------------------------------------------------------------------- /code/experiments/appinfo/test1.sql: -------------------------------------------------------------------------------- 1 | -- demonstrate what happens when you use appinfo 2 | 3 | @trace-on 4 | 5 | set appinfo on 6 | 7 | -- Note that if we use @my-handles instead of the select statement below, then 8 | -- the script name part of the MODULE name will always be my-handles.sql, which 9 | -- is not what we want. 10 | 11 | select sys_context('userenv','service_name')||'/'||sys_context('userenv','module')||'/'||sys_context('userenv','action') "service/module/action" from dual; 12 | @test2 13 | select sys_context('userenv','service_name')||'/'||sys_context('userenv','module')||'/'||sys_context('userenv','action') "service/module/action" from dual; 14 | 15 | @trace-off 16 | @my-trace-file 17 | 18 | 19 | -- If you want to chase the boundaries of what Oracle does when the script name 20 | -- is long, use the fully-qualified pathname in the @test2 call. On my system, 21 | -- I got this: 22 | 23 | -- script name: /u01/app/oracle/diag/rdbms/orclcdb/orclcdb/trace/test2.sql 24 | -- module name: 011,binds=>1) 18 | exec dbms_userdiag.check_sql_trace_event(:level) 19 | @my-trace-status 20 | 21 | exec dbms_userdiag.enable_sql_trace_event(disable=>1) 22 | exec dbms_userdiag.check_sql_trace_event(:level) 23 | 24 | -- What happens when LEVEL conflicts with, say, BINDS? 25 | exec dbms_userdiag.enable_sql_trace_event(level=>12,binds=>0) 26 | exec dbms_userdiag.check_sql_trace_event(:level) 27 | 28 | exec dbms_userdiag.enable_sql_trace_event(level=> 8,binds=>1) 29 | exec dbms_userdiag.check_sql_trace_event(:level) 30 | 31 | -- Moral: use (LEVEL) or (WAITS,BINDS,PLAN_STAT), but don't mix. 32 | 33 | -- Does SYS=>1 create a database-wide trace? 34 | 35 | -- Does SES=>:session,SER=>:serial work? 36 | 37 | -- Does PLAN_STAT=>ADAPTIVE work? Yes! 38 | select 'dbms_userdiag'; 39 | exec dbms_userdiag.enable_sql_trace_event(waits=>1,binds=>1,plan_stat=>'never') 40 | exec dbms_userdiag.check_sql_trace_event(:level) 41 | exec dbms_userdiag.enable_sql_trace_event(waits=>1,binds=>1,plan_stat=>'first_execution') 42 | exec dbms_userdiag.check_sql_trace_event(:level) 43 | exec dbms_userdiag.enable_sql_trace_event(waits=>1,binds=>1,plan_stat=>'all_executions') 44 | exec dbms_userdiag.check_sql_trace_event(:level) 45 | exec dbms_userdiag.enable_sql_trace_event(waits=>1,binds=>1,plan_stat=>'adaptive') 46 | exec dbms_userdiag.check_sql_trace_event(:level) 47 | exec dbms_userdiag.enable_sql_trace_event(waits=>1,binds=>1,plan_stat=>'nonsense') 48 | exec dbms_userdiag.check_sql_trace_event(:level) 49 | 50 | select 'dbms_monitor'; 51 | exec dbms_monitor.session_trace_enable(waits=>true,binds=>true,plan_stat=>'never') 52 | exec dbms_userdiag.check_sql_trace_event(:level) 53 | exec dbms_monitor.session_trace_enable(waits=>true,binds=>true,plan_stat=>'first_execution') 54 | exec dbms_userdiag.check_sql_trace_event(:level) 55 | exec dbms_monitor.session_trace_enable(waits=>true,binds=>true,plan_stat=>'all_executions') 56 | exec dbms_userdiag.check_sql_trace_event(:level) 57 | exec dbms_monitor.session_trace_enable(waits=>true,binds=>true,plan_stat=>'adaptive') 58 | exec dbms_userdiag.check_sql_trace_event(:level) 59 | exec dbms_monitor.session_trace_enable(waits=>true,binds=>true,plan_stat=>'nonsense') 60 | exec dbms_userdiag.check_sql_trace_event(:level) 61 | 62 | -------------------------------------------------------------------------------- /code/experiments/fetch-traces/spool-trace-fetches.sql: -------------------------------------------------------------------------------- 1 | -- create a .sql file that will fetch trace files 2 | 3 | set pagesize 0 4 | set linesize 500 5 | set trimspool on 6 | set feedback off 7 | set echo off 8 | 9 | !mkdir traces 10 | spool traces/fetch-traces.sql 11 | 12 | prompt -- Generated by spool-trace-fetches.sql 13 | prompt set pagesize 0 14 | prompt set linesize 500 15 | prompt set trimspool on 16 | prompt set feedback off 17 | prompt set echo off 18 | 19 | select distinct 'spool traces/' || trace_filename || chr(10) || 20 | ' 21 | select trim(trailing chr(10) from payload) trace 22 | from v$diag_trace_file_contents 23 | where trace_filename = ''' || trace_filename || ''' 24 | order by line_number; 25 | ' || chr(10) command 26 | from v$diag_trace_file_contents 27 | -- where trace_filename = 'orclcdb_ora_9622.trc' -- #TODO Your filter goes here. 28 | / 29 | 30 | prompt spool off 31 | spool off 32 | 33 | set termout off 34 | @traces/fetch-traces.sql 35 | set termout on 36 | 37 | 38 | -------------------------------------------------------------------------------- /code/experiments/hello-world/hello-world.sql: -------------------------------------------------------------------------------- 1 | -- "hello, world", your first trace 2 | 3 | -- This script will NOT run on an Oracle Autonomous Database system. 4 | 5 | -- See (dba|dev)-trace-permissions.sql for information about required 6 | -- privileges if the following scripts fail for you. 7 | 8 | -- connect system 9 | 10 | show user 11 | @trace-on 12 | select 'hello, world' from dual; 13 | @trace-off 14 | @my-trace-dir 15 | @my-trace-file 16 | @my-trace-content 17 | 18 | -------------------------------------------------------------------------------- /code/experiments/oradebug/tracefile_name.sql: -------------------------------------------------------------------------------- 1 | -- Insert a datestamp and trace file name into a trace file 2 | 3 | -- NOTES ONLY (does not run) by Cary Millsap 4 | 5 | -- Credit Jared Still for the idea. 6 | -- See also: 7 | -- http://www.juliandyke.com/Diagnostics/Tools/ORADEBUG/ORADEBUG.php 8 | 9 | /* 10 | 11 | The interesting thing being demonstrated below is the use of `ORADEBUG 12 | TRACEFILE_NAME` to drop a datestamp into the process's trace file, which will 13 | look like this: 14 | 15 | *** 2023-05-20T05:08:14.557296+00:00 16 | Received ORADEBUG command (#4) 'tracefile_name' from process '2772' 17 | 18 | *** 2023-05-20T05:08:14.557330+00:00 19 | Finished processing ORADEBUG command (#4) 'tracefile_name' 20 | 21 | Such a datestamp can be useful for marking the beginning and ending of a user's 22 | online experience within the trace. Of course, if you can get a tightly scoped 23 | trace file by enabling and disabling a trace at exactly the right times (such 24 | as with DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE or SERV_MOD_ACT_TRACE_ENABLE), 25 | then you should do that. 26 | 27 | Before you can use ORADEBUG TRACEFILE_NAME, you'll need to find the 28 | V$PROCESS.PID value of the session you want to trace. You can enable tracing 29 | for a given session with DBMS_MONITOR (that's what I recommend), or you can use 30 | the ORADEBUG EVENT syntax. 31 | 32 | */ 33 | 34 | oradebug setorapid PID 35 | 36 | oradebug event 10046 trace name context forever, level 8 37 | oradebug tracefile_name 38 | 39 | -- User's work to be traced happens here. 40 | 41 | oradebug tracefile_name 42 | oradebug event 10046 trace name context off 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /code/experiments/trace-line-truncation/t.sql: -------------------------------------------------------------------------------- 1 | -- test for v$diag_trace_file_contents truncation 2 | 3 | /* 4 | 5 | https://forums.oracle.com/ords/apexds/post/extend-v-diag-trace-file-contents-so-multiple-chunks-of-a-l-0490 6 | 7 | - Martin Berger and Jeff Holt discovered that Oracle: 8 | - segments long lines into chunks 9 | - the chunks all have the same line number 10 | - there is nothing exposed in v$diag_trace_file_contents to allow reliable sorting of the chunks 11 | 12 | - Cary Millsap and Jeff Holt discovered that Oracle: 13 | - will truncate long SELECT clause constants 14 | 15 | */ 16 | 17 | 18 | -- Cary Millsap test 19 | 20 | -- non-ADB 21 | -- The SELECT string has 4,000 dots in it, and some extra characters at its beginning and end. 22 | @trace-on 23 | select 'BEGIN 4,000 DOTS................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................END' 24 | from dual; 25 | @trace-off 26 | @my-trace-file 27 | @my-trace-content 28 | -- In V$DIAG_TRACE_FILE_CONTENTS, the "END" at the tail of the SELECT string is truncated. 29 | 30 | -- ADB 31 | -- The SELECT string has 4,000 dots in it, and some extra characters at its beginning and end. 32 | alter session set sql_trace=true; 33 | select 'BEGIN 4,000 DOTS................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................END' 34 | from dual; 35 | alter session set sql_trace=false; 36 | @adb/my-trace-content 37 | -- In SESSION_CLOUD_TRACE, the "END" at the tail of the SELECT string is truncated. 38 | 39 | -------------------------------------------------------------------------------- /code/experiments/trace-size-estimate/trace-size.sql: -------------------------------------------------------------------------------- 1 | -- trace file size estimator 2 | 3 | -- Martin Berger has suggested estimating trace sizes and IOPS by using the 4 | -- trace rates and sizes published in the Tracing Oracle book, combined with 5 | -- data from v$sysstat: 6 | -- 7 | -- - user calls dbcall count 8 | -- - non-idle wait count underestimate of syscall count 9 | 10 | -- - parse count (total) overestimate of PARSING IN CURSOR count 11 | -- - user commits XCTEND rlbk=0 count 12 | -- - user rollbacks XCTEND rlbk=1 count 13 | 14 | -- - execute count might help with BINDS size estimation 15 | 16 | -- It's a good idea, especially for calculating lines emitted by the 17 | -- WAITS=>TRUE parameter. 18 | 19 | -- The trickiest problem is probably going to be estimating the cost of 20 | -- BINDS=>TRUE. That information will probably need to come from 21 | -- V$SQL_BIND_DATA or similar. By the time we hack through this, it's probably 22 | -- easier to just test and measure. (See scripts/disk-consumption-rate.pl). 23 | 24 | -------------------------------------------------------------------------------- /code/experiments/triggers/trace-trigger.sql: -------------------------------------------------------------------------------- 1 | -- create a trigger to enable tracing 2 | 3 | create or replace trigger mr_trace_aftlogon_all 4 | after logon on schema 5 | begin 6 | sys.dbms_session.session_trace_enable; 7 | exception when others then null; 8 | end; 9 | / 10 | -------------------------------------------------------------------------------- /code/experiments/triggers/trace-user-machine-program.sql: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2019, 2022 Method R Corporation 2 | 3 | -- Usage trace-machine-program enable|disable 4 | 5 | set serveroutput on 6 | 7 | define usr_name=&3 8 | define pgm_name=&4 9 | define mach_name=&5 10 | 11 | create or replace trigger &2.trg_trace_directive 12 | after logon on schema 13 | begin 14 | for s in (select * from SYS.V_$SESSION where SID = sys_context('userenv', 'SID')) loop 15 | if '&usr_name' = s.USERNAME and '&pgm_name' = s.PROGRAM and '&mach_name' = s.MACHINE then 16 | dbms_monitor.session_trace_enable(null, null, true, false, 'first_execution'); 17 | end if; 18 | end loop; 19 | exception when others then null; 20 | end; 21 | / 22 | show errors 23 | 24 | alter trigger &2.trg_trace_directive &1; 25 | 26 | 27 | declare 28 | n number := 0; 29 | begin 30 | for s in (select * from SYS.V_$SESSION where '&usr_name' = USERNAME and '&pgm_name' = PROGRAM and '&mach_name' = MACHINE) loop 31 | if '&1' = 'enable' then 32 | dbms_monitor.session_trace_enable(s.sid, s.serial#, true, false, 'first_execution'); 33 | n := n + 1; 34 | else 35 | dbms_monitor.session_trace_disable(s.sid, s.serial#); 36 | n := n + 1; 37 | end if; 38 | end loop; 39 | if '&1' = 'enable' then 40 | dbms_output.put_line('enabled trace for ' || n || ' sessions'); 41 | else 42 | dbms_output.put_line('disabled trace for ' || n || ' sessions'); 43 | end if; 44 | end; 45 | / 46 | 47 | -------------------------------------------------------------------------------- /code/scripts/GetTraceFile-setup.sql: -------------------------------------------------------------------------------- 1 | -- set up the directory object for GetTraceFile 2 | 3 | -- Copyright (c) 2021 Method R Corporation 4 | 5 | select directory_name from all_directories where directory_path = (select value from v$diag_info where name = 'Diag Trace'); 6 | 7 | -- If the query returns no rows, then you'll need to create a directory object and grant read privilege on it. 8 | -- #TODO 9 | 10 | create or replace directory METHODR_UDUMP_1 as '/u01/app/oracle/diag/rdbms/ora193/ora193/trace'; #TODO 11 | grant read on #TODO to #TODO ; 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /code/scripts/GetTraceFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | Fetch Oracle trace files 3 | 4 | The code that Amazon recommends for fetching trace data from Amazon RDS 5 | doesn't work quite right; it fails to copy trace file lines that are longer 6 | than 400 characters. 7 | 8 | https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.Oracle.html#USER_LogAccess.Concepts.Oracle.WorkingWithTracefiles 9 | 10 | This program works, irrespective of trace line length. 11 | */ 12 | 13 | // Copyright (c) 2021 Method R Corporation 14 | 15 | import java.io.*; 16 | import java.sql.*; 17 | import oracle.jdbc.*; 18 | 19 | public class GetTraceFile { 20 | 21 | private Connection conn; 22 | private CallableStatement stm; 23 | private String connurl; 24 | private String oradir; 25 | private int bufsz = 512; 26 | 27 | public GetTraceFile (String connurl, String oradir) { 28 | this.connurl = connurl; 29 | this.oradir = oradir; 30 | } 31 | 32 | private void read (OracleBfile b) throws Exception { 33 | b.openFile(); 34 | InputStream s = b.getBinaryStream(); 35 | InputStreamReader r = new InputStreamReader(s); 36 | int nb; 37 | byte[] ba = new byte[bufsz]; 38 | while ((nb = s.read(ba)) != -1) 39 | System.out.write(ba, 0, nb); 40 | b.closeFile(); 41 | } 42 | 43 | // Call this before calling get. 44 | public void init () throws Exception { 45 | if (conn == null) 46 | conn = DriverManager.getConnection(this.connurl); 47 | } 48 | 49 | // Call this after calling init. 50 | public void get (String trcfilename) throws Exception { 51 | if (this.stm == null) 52 | this.stm = conn.prepareCall("select bfilename(?,?) from dual"); 53 | this.stm.setString(1, this.oradir); 54 | this.stm.setString(2, trcfilename); 55 | OracleResultSet r = (OracleResultSet) this.stm.executeQuery(); 56 | while (r.next()) // By definition this has to iterate exactly 0 or 1 time 57 | read(r.getBFILE(1)); 58 | r.close(); 59 | } 60 | 61 | // Call this when you're done getting trace files. 62 | public void done () throws Exception { 63 | if (this.stm != null) 64 | this.stm.close(); 65 | if (this.conn != null) 66 | this.conn.close(); 67 | } 68 | 69 | // Use this if you want only one trace file. 70 | public static void main (String[] args) throws Exception { 71 | GetTraceFile gtf = new GetTraceFile(args[0], args[1]); 72 | gtf.init(); 73 | gtf.get(args[2]); 74 | gtf.done(); 75 | } 76 | 77 | } 78 | 79 | /* 80 | 81 | $ javac -cp .:ojdbc8.jar GetTraceFile.java 82 | $ java -cp .:ojdbc8.jar GetTraceFile jdbc:oracle:thin:jeff/jeff@localhost:55210:ora193 METHODR_UDUMP_1 ora193_dia0_8489_base_1.trc > x 83 | $ head -1 x 84 | Trace file /u01/app/oracle/diag/rdbms/ora193/ora193/trace/ora193_dia0_8489_base_1.trc 85 | $ diff x /u01/app/oracle/diag/rdbms/ora193/ora193/trace/ora193_dia0_8489_base_1.trc 86 | $ 87 | 88 | */ 89 | -------------------------------------------------------------------------------- /code/scripts/GetTraceFile.pl: -------------------------------------------------------------------------------- 1 | # Fetch Oracle trace files 2 | # 3 | # The code that Amazon recommends for fetching trace data from Amazon RDS 4 | # doesn't work quite right; it fails to copy trace file lines that are longer 5 | # than 400 characters. 6 | # 7 | # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.Oracle.html#USER_LogAccess.Concepts.Oracle.WorkingWithTracefiles 8 | # 9 | # This program works, irrespective of trace line length. 10 | 11 | # Copyright (c) 2021 Method R Corporation 12 | 13 | use strict; 14 | use warnings; 15 | use DBI; 16 | 17 | my ($dbauth, $dirname, $filename) = @ARGV; 18 | my $dbh = DBI->connect('dbi:Oracle:', $dbauth) or die; 19 | my $bufsz = 512; 20 | 21 | my $stm = "select bfilename(?, ?) from dual"; 22 | my $stmh = $dbh->prepare($stm, {ora_auto_lob=>0}) or die; 23 | $stmh->execute($dirname, $filename); 24 | my ($loc) = $stmh->fetchrow_array(); 25 | for (my $off=1; 1; $off += $bufsz) { 26 | my $piece = $dbh->ora_lob_read($loc, $off, $bufsz); 27 | last if length($piece) == 0; 28 | print $piece; 29 | } 30 | $stmh->finish; 31 | $dbh->disconnect; 32 | 33 | __END__ 34 | 35 | $ perl gettrc.pl jeff/jeff METHODR_UDUMP_1 ora193_dia0_8489_base_1.trc > x 36 | $ head -1 x 37 | Trace file /u01/app/oracle/diag/rdbms/ora193/ora193/trace/ora193_dia0_8489_base_1.trc 38 | $ diff x /u01/app/oracle/diag/rdbms/ora193/ora193/trace/ora193_dia0_8489_base_1.trc 39 | $ 40 | -------------------------------------------------------------------------------- /code/scripts/df-rate.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Print number of days until filesystem fills. 4 | 5 | use strict; 6 | use warnings; 7 | use File::Basename; 8 | use Getopt::Long; 9 | use Time::Piece; 10 | use File::Spec; 11 | use Pod::Usage; 12 | 13 | our $Program = fileparse $0, qr(\..*); 14 | 15 | our %Opt = ( 16 | debug => 0, 17 | head => 1, 18 | ofile => '', 19 | ); 20 | our %Options = ( 21 | "debug" => \$Opt{debug}, 22 | "help|?" => sub { pod2usage(-input=>\*main::DATA, -verbose => 1, -exit => 0); }, 23 | "man" => sub { pod2usage(-input=>\*main::DATA, -verbose => 2, -exit => 0); -formatter => "Pod::Text::Termcap"; }, 24 | "usage" => sub { pod2usage(-input=>\*main::DATA, -verbose => 0, -exit => 0); }, 25 | # 26 | "head!" => \$Opt{head}, # Print header. 27 | "o" => \$Opt{ofile}, # Not implemented (easy enough to do on the command line with `tee`). 28 | ); 29 | GetOptions(%Options) or die; 30 | 31 | my $DEBUG = $Opt{debug}; 32 | 33 | my ($dir, $interval, $count) = ( 34 | $ARGV[0] // ".", # Directory name. 35 | $ARGV[1] // 1, # Interval duration in seconds. 36 | $ARGV[2] // 1000, # Number of intervals. 37 | ); 38 | printf "%s '%s' %d %d\n\n", basename($0), File::Spec->rel2abs($dir), $interval, $count; 39 | 40 | my $format = "%Y-%m-%dT%H:%M:%S"; # ISO 8601. 41 | 42 | sub _date { 43 | # Execute the date command. 44 | chomp(my $d = qx(date "+$format")); # `date` prints a newline, so chomp it. 45 | return $d; 46 | } 47 | sub df($) { 48 | # Execute the df command, return kilobytes. 49 | # ASSERT: `df` returns "Available" in the fourth field of the final line of its output. 50 | # ASSERT: `df -k` returns 1024-byte blocks. 51 | my ($dir) = @_; 52 | my $df = qx(df -k "$dir" | tail -1); 53 | return (split /\s+/, $df)[3]; 54 | } 55 | sub head() { 56 | return unless $Opt{head}; 57 | printf "%19s %10s %10s %15s\n", "Time", "GB free", "GB/s used", "Days until full"; 58 | } 59 | sub p($$$$) { 60 | # Print the rates from (date1,df1) to (date2,df2). 61 | my ($date1, $df1, $date2, $df2) = @_; 62 | 63 | # Print date columns. 64 | my $delta_s = Time::Piece->strptime($date2, $format) - Time::Piece->strptime($date1, $format); 65 | return if $delta_s == 0; 66 | printf "%19s", $date2; # "Time" 67 | printf " "; 68 | 69 | # Print GB free columns. 70 | printf "%10d", $df2 / (1e9/1e3); # "GB free" 71 | printf " "; 72 | 73 | # Print consumption rate in KB/s. 74 | my $delta_df = $df1 - $df2; # KB consumed this interval. 75 | my $kbps = $delta_df/$delta_s; # KB/s at which freespace is being consumed. 76 | printf "%10.6f", $kbps / (1e9/1e3); # "GB/s used" 77 | printf " "; 78 | 79 | # Print days remaining at this rate. 80 | if ($kbps > 0) { 81 | my $days = $df2/$kbps/(60*60*24); # k/(k/s)/(s/m*m/h*h/d) = d. 82 | printf "%15.1f", $days; 83 | } else { 84 | printf "%15s", "+INF"; 85 | } 86 | print "\n"; 87 | } 88 | $SIG{INT} = sub { exit; }; # Execute the END block upon Ctrl-C. 89 | 90 | my ($date0, $du0); # First (date, du) tuple. 91 | my ($date1, $du1); # Prior (date, du) tuple. 92 | my ($date2, $du2); # Current (date, du) tuple. 93 | 94 | ($date0, $du0) = ($date1, $du1) = ($date2, $du2) = (_date, df($dir)); 95 | head(); 96 | for (1..$count) { 97 | sleep($interval); 98 | ($date2, $du2) = (_date, df($dir)); 99 | p($date1, $du1, $date2, $du2); 100 | ($date1, $du1) = ($date2, $du2); 101 | } 102 | 103 | END { 104 | print "\n"; 105 | head(); 106 | p($date0, $du0, $date2, $du2); 107 | } 108 | 109 | 110 | __DATA__ 111 | 112 | 113 | =head1 NAME 114 | 115 | df-rate - file system full estimator 116 | 117 | 118 | =head1 SYNOPSIS 119 | 120 | df-rate [ I ] [ I [ I [ I ] ] ] 121 | 122 | 123 | =head1 DESCRIPTION 124 | 125 | The B program executes the B command upon the fileysstem 126 | containing I, once every I seconds, for I 127 | iterations. It will write a line to standard output for each iteration. 128 | 129 | If no parameter values are specified, the program will run as if you had typed 130 | the following: 131 | 132 | df-rate . 1 1000 133 | 134 | That is, the I value defaults to the current working directory, 135 | I defaults to 1 seconds, and I defaults to 1,000 intervals. 136 | 137 | After reporting its final interval, B prints a line that summarizes 138 | over all the intervals combined, its estimate of when your filesystem will 139 | fill. 140 | 141 | To terminate the program before it reaches the specified interval count, 142 | interrupt it with Ctrl-C. The program will then print its summary line and 143 | terminate. 144 | 145 | 146 | =head1 OPTIONS 147 | 148 | =over 149 | 150 | =item --head 151 | 152 | Print column headings (default). Use B<--nohead> to suppress. 153 | 154 | =item --man 155 | 156 | Print the manual page and exit. 157 | 158 | =back 159 | 160 | 161 | =head1 EXAMPLES 162 | 163 | How long will it take for a database-wide trace to consume our entire 164 | DIAGNOSTIC_DEST filesystem? B makes it easy to know, after running 165 | a short 10-minute test. 166 | 167 | To test B, use F. 168 | 169 | 170 | =head1 AUTHOR 171 | 172 | Cary Millsap 173 | 174 | 175 | =head1 COPYRIGHT AND LICENSE 176 | 177 | Copyright (c) 2022, 2024 Cary Millsap 178 | 179 | -------------------------------------------------------------------------------- /code/scripts/du-rate.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Calculate disk consumption rate. 4 | 5 | use strict; 6 | use warnings; 7 | use File::Basename; 8 | use Getopt::Long; 9 | use Time::Piece; 10 | use File::Spec; 11 | use Pod::Usage; 12 | 13 | our $Program = fileparse $0, qr(\..*); 14 | 15 | our %Opt = ( 16 | debug => 0, 17 | ofile => '', 18 | unit => 'MB/h', 19 | ); 20 | our %Options = ( 21 | "debug" => \$Opt{debug}, 22 | "help|?" => sub { pod2usage(-input=>\*main::DATA, -verbose => 1, -exit => 0); }, 23 | "man" => sub { pod2usage(-input=>\*main::DATA, -verbose => 2, -exit => 0); -formatter => "Pod::Text::Termcap"; }, 24 | "usage" => sub { pod2usage(-input=>\*main::DATA, -verbose => 0, -exit => 0); }, 25 | # 26 | "o" => \$Opt{ofile}, # Not implemented (easy enough to do on the command line with `tee`). 27 | "unit=s" => \$Opt{unit}, 28 | ); 29 | GetOptions(%Options) or die; 30 | 31 | my $DEBUG = $Opt{debug}; 32 | my $WORKING = 0; 33 | 34 | my %bytes = ( 35 | "B" => 1, 36 | "KB" => 1e3, 37 | "MB" => 1e6, 38 | "GB" => 1e9, 39 | "TB" => 1e12, 40 | "PB" => 1e15, 41 | ); 42 | my %seconds = ( 43 | "s" => 1, 44 | "m" => 60, 45 | "h" => 60*60, 46 | "d" => 60*60*24, 47 | "w" => 60*60*24*7, 48 | ); 49 | 50 | my ($qunit, $tunit); 51 | my ($bytes, $seconds); 52 | { 53 | ($qunit, $tunit) = split('/', $Opt{unit}); 54 | $bytes = $bytes{$qunit}; 55 | $seconds = $seconds{$tunit}; 56 | printf "Opt{unit}='%s' qunit='%s' tunit='%s' bytes='%d' seconds='%d'\n", $Opt{unit}, $qunit, $tunit, $bytes, $seconds if $DEBUG; 57 | die "unrecognized quantity unit '$qunit'; should be one of (B KB MB GB TB PB)" if !defined $bytes; 58 | die "unrecognized time unit '$tunit'; should be one of (s m h d w)" if !defined $seconds; 59 | } 60 | 61 | my ($dir, $interval, $count) = ( 62 | $ARGV[0] // ".", # Directory name. 63 | $ARGV[1] // 1, # Interval duration in seconds. 64 | $ARGV[2] // 1000, # Number of intervals. 65 | ); 66 | printf "%s '%s' %d %d\n\n", basename($0), File::Spec->rel2abs($dir), $interval, $count; 67 | 68 | my $format = "%Y-%m-%dT%H:%M:%S"; # ISO 8601. 69 | 70 | sub d { 71 | # Execute the date command. 72 | chomp(my $d = qx(date "+$format")); # `date` prints a newline, so chomp it. 73 | return $d; 74 | } 75 | sub du($) { 76 | # Execute the du command, return bytes. 77 | # ASSERT: `du -s` returns bytes used in the first field of its output. 78 | # ASSERT: `du -k` returns 1024-byte blocks. 79 | my ($dir) = @_; 80 | return 0 if not -d "$dir"; 81 | my $du = qx(du -ks "$dir"); 82 | return (split /\s+/, $du)[0] * 1024; 83 | } 84 | sub df($) { 85 | # Execute the df command, return bytes. 86 | # ASSERT: `df` returns "Available" in the fourth field of the final line of its output. 87 | # ASSERT: `df -k` returns 1024-byte blocks. 88 | my ($dir) = @_; 89 | my $df = qx(df -k "$dir" | tail -1); 90 | return (split /\s+/, $df)[3] * 1024; 91 | } 92 | sub p($$$$) { 93 | # Print the rates from (date1,du1) to (date2,du2). 94 | my ($date1, $du1, $date2, $du2) = @_; 95 | my $s = Time::Piece->strptime($date2, $format) - Time::Piece->strptime($date1, $format); 96 | return if $s == 0; 97 | my $du = $du2 - $du1; 98 | my $bps = $du/$s; 99 | # Next stats are in s, irrespective of the chosen time unit. 100 | printf "%s … %s = %d s ", $date1, $date2, $s; 101 | # Next stats are in KB, irrespective of the chosen quantity unit. 102 | # printf "%d KB … %d KB = %d KB", $du1/$bytes{KB}, $du2/$bytes{KB}, $du/$bytes{KB}; 103 | printf " %.1f %s/%s", $bps/($bytes/$seconds), $qunit, $tunit; 104 | my $df = df($dir); 105 | printf " %10d %s free", $df/$bytes, $qunit; 106 | printf " "; 107 | if ($bps <= 0) { 108 | printf "not filling"; 109 | } else { 110 | printf "%.1f days until full", $df/$bps/$seconds{d}; 111 | } 112 | print "\n"; 113 | } 114 | $SIG{INT} = sub { exit; }; # Execute the END block upon Ctrl-C. 115 | 116 | my ($date0, $du0); # First ever (date, du) tuple. 117 | my ($date1, $du1); # Prior (date, du) tuple. 118 | my ($date2, $du2); # Current (date, du) tuple. 119 | 120 | ($date0, $du0) = ($date1, $du1) = ($date2, $du2) = (d, du($dir)); 121 | for (1..$count) { 122 | sleep($interval); 123 | ($date2, $du2) = (d, du($dir)); 124 | p($date1, $du1, $date2, $du2); 125 | ($date1, $du1) = ($date2, $du2); 126 | } 127 | 128 | END { 129 | print "\n"; 130 | p($date0, $du0, $date2, $du2); 131 | } 132 | 133 | 134 | __DATA__ 135 | 136 | 137 | =head1 NAME 138 | 139 | du-rate - calculate disk consumption rate 140 | 141 | 142 | =head1 SYNOPSIS 143 | 144 | du-rate [ I ] [ I [ I [ I ] ] ] 145 | 146 | 147 | =head1 DESCRIPTION 148 | 149 | The B program executes the B command upon 150 | I, once every I seconds, for I iterations. It will 151 | write a line to standard output for each iteration. 152 | 153 | If no parameter values are specified, the program will run as if you typed the 154 | following: 155 | 156 | du-rate . 10 1000 157 | 158 | That is, the I value defaults to the current working directory, 159 | I defaults to 10 seconds, and I defaults to 1,000 intervals. 160 | 161 | After reporting its final interval, B prints a line that 162 | summarizes all the disk consumption that has occurred since the program was 163 | executed. To terminate the program before it reaches the specified interval 164 | count, simply press Ctrl-C. The program will then print its summary line and 165 | terminate. 166 | 167 | 168 | =head1 OPTIONS 169 | 170 | =over 171 | 172 | =item --man 173 | 174 | Print the manual page and exit. 175 | 176 | =item --unit=I 177 | 178 | Report in the given unit, expressed in "Q/T" format (quantity per unit of 179 | time). Quantity can be any of B, KB, MB, GB, TB, or PB. Time can be any of s, 180 | m, h, d, w (seconds, minutes, hours, days, weeks). Default is "GB/h". 181 | 182 | =back 183 | 184 | 185 | 186 | =head1 EXAMPLES 187 | 188 | We created this tool because we had a customer who needed to know how many days 189 | they could leave an Oracle database-wide trace enabled without running out of 190 | disk space. They knew how many terabytes of available storage they had, but 191 | they didn't know how quickly their trace would consume that space. We executed 192 | a few 10-minute tests during which we would enable database-wide tracing and 193 | then measure the consumption rate in the Oracle Database DIAGNOSTIC_DEST 194 | directory with B. With this information, we could estimate how many 195 | days we'd be able to trace before worrying about running out of space. 196 | 197 | To test B, use F. 198 | 199 | 200 | =head1 AUTHOR 201 | 202 | Cary Millsap 203 | 204 | 205 | =head1 COPYRIGHT AND LICENSE 206 | 207 | Copyright (c) 2022, 2024 Cary Millsap 208 | 209 | -------------------------------------------------------------------------------- /code/scripts/fill-disk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fill a disk (for testing disk-consumption-rate.pl) 4 | 5 | output_dir="DELETE_ME" 6 | output_file="delete_me.img" 7 | output_path="$output_dir/$output_file" 8 | tmp_file="tmp.img" 9 | 10 | cleanup() { 11 | # One could clean up here, but that throws off the disk-consumption-rate.pl totals. 12 | # Cleanup is thus left for the user to take care of. 13 | # 14 | # rm "$output_path" # one component at a time, ... 15 | # rmdir "$output_dir" # ...just to be safe 16 | printf "\n" 17 | printf "$output_path\n" 18 | ls -lh "./$output_dir" | tail -1 19 | exit 0 20 | } 21 | trap cleanup SIGINT 22 | 23 | rm "$output_path" # No need having the file start off big. 24 | mkdir -p "$output_dir" 25 | 26 | while true; do 27 | dd if=/dev/urandom of="$tmp_file" bs=1024 count=100 conv=notrunc oflag=fsync status=none # speed=2m 28 | cat "$tmp_file" >> "$output_path" 29 | rm "$tmp_file" 30 | printf "." 31 | sleep 1 32 | done 33 | 34 | 35 | -------------------------------------------------------------------------------- /code/scripts/purge-traces.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Your .trc directory name goes here 4 | TRCDIR=/DIR/diag/rdbms/DB_UNIQUE_NAME/INSTANCE_NAME/trace/ 5 | 6 | N=14 # 7, 14, 28 are good numbers for most people 7 | 8 | # #TODO - Use lsof or ps to ensure that we're not going to delete an open file. 9 | 10 | find $TRCDIR -type f -name \*.tr[cm] -mtime +$N -delete 11 | 12 | -------------------------------------------------------------------------------- /code/sql/adb/my-trace-content.sql: -------------------------------------------------------------------------------- 1 | -- print my trace content (ADB) 2 | 3 | select trace from session_cloud_trace order by row_number; 4 | 5 | -------------------------------------------------------------------------------- /code/sql/adb/trace-off.sql: -------------------------------------------------------------------------------- 1 | -- disable tracing for my session (ADB) 2 | 3 | alter session set sql_trace=false; 4 | 5 | 6 | -------------------------------------------------------------------------------- /code/sql/adb/trace-on.sql: -------------------------------------------------------------------------------- 1 | -- enable tracing for my session (ADB) 2 | 3 | alter session set sql_trace=true; 4 | 5 | -------------------------------------------------------------------------------- /code/sql/enabled-traces.sql: -------------------------------------------------------------------------------- 1 | -- print info about enabled (standing) traces 2 | 3 | -- Note that this query will report only upon traces enabled with: 4 | -- - dbms_monitor.client_id_trace_enable 5 | -- - dbms_monitor.serv_mod_act_trace_enable 6 | -- - dbms_monitor.database_trace_enable 7 | 8 | select 9 | instance_name 10 | , trace_type 11 | , primary_id 12 | , qualifier_id1 13 | , qualifier_id2 14 | , waits 15 | , binds 16 | , plan_stats 17 | from 18 | dba_enabled_traces 19 | / 20 | 21 | 22 | -- Note that this command (below) will report only upon traces enabled with oradebug. 23 | 24 | -- oradebug setmypid 25 | -- oradebug eventdump system 26 | -------------------------------------------------------------------------------- /code/sql/inventory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Create script inventory. 4 | 5 | # Assumptions: 6 | # - All files have /.sql/ name suffix. 7 | # - First line of each file matches /^-- program description/. 8 | # - All files match *.sql or */*.sql 9 | 10 | for FILENAME in *.sql */*.sql 11 | do 12 | echo "$FILENAME" $(head -1 $FILENAME | sed "s/^--/-/g") 13 | done | nl 14 | 15 | -------------------------------------------------------------------------------- /code/sql/login.sql: -------------------------------------------------------------------------------- 1 | -- execute upon SQLcl startup 2 | 3 | -- set sqlformat default 4 | set heading off 5 | set sqlformat ansiconsole 6 | set pagesize 9999 7 | set sqlprompt "_user'@'_connect_identifier _privilege > " 8 | -------------------------------------------------------------------------------- /code/sql/mr-packages/1-owner.sql: -------------------------------------------------------------------------------- 1 | -- create user MR with appropriate permissions 2 | 3 | -- Copyright (c) 2022, 2023 Method R Corporation 4 | 5 | 6 | -- You must be SYSDBA to perform the required grants. 7 | connect sys/oracle@orcl as sysdba 8 | 9 | drop user method_r cascade; -- Fresh start. 10 | create user method_r; -- This user will own the packages. 11 | -- create user method_r identified by method_r; -- No need to actually connect as METHOD_R. 12 | -- grant create session to method_r; -- No need to actually connect as METHOD_R. 13 | -- grant create procedure to method_r; -- We'll create the procedures connected as SYS. 14 | 15 | grant execute on sys.dbms_application_info to method_r; -- For setting and getting Oracle user session handle attributes. 16 | grant execute on sys.dbms_session to method_r; -- Won't use session_trace_(en|dis)able, but will use set_identifier. 17 | grant execute on sys.dbms_monitor to method_r; -- Trace (en|dis)able procedures. 18 | grant execute on sys.dbms_assert to method_r; -- To prevent SQL injection. 19 | grant read on sys.v_$instance to method_r; -- Needed for its data types. 20 | grant read on sys.v_$session to method_r; -- Needed for its data types. 21 | 22 | -- grant read on sys.v_$diag_info to method_r; 23 | -- grant read on sys.v_$statistics_level to method_r; 24 | 25 | grant read on sys.v_$diag_trace_file_contents to method_r; -- #TODO not used yet 26 | 27 | -------------------------------------------------------------------------------- /code/sql/mr-packages/2-mrdev.sql: -------------------------------------------------------------------------------- 1 | -- bundle the trace features that a developer needs 2 | 3 | -- WARNING: Nothing in this script will work in Oracle Autonomous Database on 4 | -- shared infrastructure (ADB-S), where Oracle have intentionally prohibited 5 | -- any session from using DBMS_MONITOR or any form of ALTER SESSION SET EVENTS 6 | -- either directly or indirectly (as DBMS_SESSION.SESSION_TRACE_ENABLE does). 7 | 8 | -- Copyright (c) 2022, 2023 Method R Corporation 9 | 10 | 11 | -- You must be SYSDBA to perform the required grants. 12 | connect sys/oracle@orcl as sysdba 13 | 14 | 15 | create or replace package method_r.mrdev authid definer as 16 | 17 | procedure trace_on( 18 | binds in boolean default false 19 | , plans in varchar2 default 'first_execution' 20 | , stats in varchar2 default 'typical' 21 | ); 22 | procedure trace_off; 23 | 24 | procedure set_module(module in varchar2 default null); 25 | procedure set_action(action in varchar2 default null); 26 | procedure set_client(client in varchar2 default null); 27 | 28 | function get_service return varchar2; 29 | function get_module return varchar2; 30 | function get_action return varchar2; 31 | function get_client return varchar2; 32 | function get_filename return varchar2; 33 | 34 | -- function get_content return ???; -- #TODO return what? 35 | 36 | end mrdev; 37 | / 38 | 39 | 40 | create or replace package body method_r.mrdev as 41 | 42 | procedure trace_on( 43 | binds in boolean default false 44 | , plans in varchar2 default 'first_execution' 45 | , stats in varchar2 default 'typical' 46 | ) as 47 | s varchar2(64 char) := dbms_assert.simple_sql_name(stats); 48 | begin 49 | execute immediate q'[alter session set max_dump_file_size=unlimited]'; 50 | execute immediate q'[alter session set statistics_level=]'||s; 51 | dbms_monitor.session_trace_enable( 52 | waits => true 53 | , binds => binds 54 | , plan_stat => plans 55 | ); 56 | 57 | -- There are at least three ways we could have enabled tracing. 58 | 59 | -- ALTER SESSION is ugly and unsafe: 60 | 61 | -- execute immediate q'[alter session set events 'sql_trace wait=true,bind=]'||b||q'[,plan_stat=]'||p||q'[']'; 62 | 63 | -- DBMS_SESSION sounds like it should be the right package to use, but it 64 | -- uses invoker's rights, which requires its callers--*anywhere* in the 65 | -- call stack!--to have the ALTER SESSION system privilege. It's not good 66 | -- for developers to have ALTER SESSION. 67 | 68 | -- DBMS_MONITOR is definer's rights and does everything we need, cleanly 69 | -- and safely. 70 | 71 | end; 72 | 73 | procedure trace_off as 74 | begin 75 | dbms_monitor.session_trace_disable; 76 | end; 77 | 78 | procedure set_module( 79 | module in varchar2 default null 80 | ) as 81 | begin 82 | dbms_application_info.set_module(module_name=>module, action_name=>null); 83 | end; 84 | 85 | procedure set_action( 86 | action in varchar2 default null 87 | ) as 88 | begin 89 | dbms_application_info.set_action(action_name=>action); 90 | end; 91 | 92 | procedure set_client( 93 | client in varchar2 default null 94 | ) as 95 | begin 96 | dbms_session.set_identifier(client_id=>client); -- Bizarre that there's no dbms_application_info.set_identifier. 97 | end; 98 | 99 | function get_service return varchar2 100 | as 101 | begin 102 | return sys_context('userenv','service_name'); -- Bizarre that "_name" is in the name. 103 | end; 104 | 105 | function get_module return varchar2 106 | as 107 | begin 108 | return sys_context('userenv','module'); 109 | end; 110 | 111 | function get_action return varchar2 112 | as 113 | begin 114 | return sys_context('userenv','action'); 115 | end; 116 | 117 | function get_client return varchar2 118 | as 119 | begin 120 | return sys_context('userenv','client_identifier'); 121 | end; 122 | 123 | function get_filename return varchar2 124 | as 125 | f sys.v_$diag_info.value%type; 126 | begin 127 | select value into f from v$diag_info where name='Default Trace File'; 128 | return f; 129 | end; 130 | 131 | end mrdev; 132 | / 133 | 134 | show errors 135 | 136 | 137 | -------------------------------------------------------------------------------- /code/sql/mr-packages/3-mrdba.sql: -------------------------------------------------------------------------------- 1 | -- bundle the trace features that a DBA needs 2 | 3 | -- WARNING: Nothing in this script will work in Oracle Autonomous Database on 4 | -- shared infrastructure (ADB-S), where Oracle have intentionally prohibited 5 | -- any session from using DBMS_MONITOR or any form of ALTER SESSION SET EVENTS 6 | -- either directly or indirectly (as DBMS_SESSION.SESSION_TRACE_ENABLE does). 7 | 8 | -- Copyright (c) 2022, 2023 Method R Corporation 9 | 10 | 11 | -- You must be SYSDBA to perform the required grants. 12 | connect sys/oracle@orcl as sysdba 13 | 14 | 15 | create or replace package method_r.mrdba authid definer as 16 | 17 | all_modules sys.v_$session.module%type := dbms_monitor.all_modules; 18 | all_actions sys.v_$session.action%type := dbms_monitor.all_actions; 19 | all_instances sys.v_$instance.instance_name%type := null; 20 | 21 | procedure session_on( 22 | sid in binary_integer default null 23 | , serial in binary_integer default null 24 | , binds in boolean default false 25 | , plans in varchar2 default 'first_execution' 26 | ); 27 | procedure client_on( 28 | client in varchar2 29 | , binds in boolean default false 30 | , plans in varchar2 default 'first_execution' 31 | ); 32 | procedure handle_on( 33 | service in varchar2 default sys_context('userenv','service_name') 34 | , module in varchar2 default all_modules 35 | , action in varchar2 default all_actions 36 | , binds in boolean default false 37 | , plans in varchar2 default 'first_execution' 38 | , instance in varchar2 default all_instances 39 | ); 40 | procedure database_on( 41 | binds in boolean default false 42 | , plans in varchar2 default 'first_execution' 43 | , instance in varchar2 default all_instances 44 | ); 45 | 46 | procedure session_off( 47 | sid in binary_integer default null 48 | , serial in binary_integer default null 49 | ); 50 | procedure client_off( 51 | client in varchar2 52 | ); 53 | procedure handle_off( 54 | service in varchar2 default sys_context('userenv','service_name') 55 | , module in varchar2 default all_modules 56 | , action in varchar2 default all_actions 57 | , instance in varchar2 default all_instances 58 | ); 59 | procedure database_off( 60 | instance in varchar2 default all_instances 61 | ); 62 | 63 | end mrdba; 64 | / 65 | 66 | 67 | create or replace package body method_r.mrdba as 68 | 69 | procedure session_on( 70 | sid in binary_integer default null 71 | , serial in binary_integer default null 72 | , binds in boolean default false 73 | , plans in varchar2 default 'first_execution' 74 | ) as 75 | begin 76 | dbms_monitor.session_trace_enable( 77 | session_id => sid 78 | , serial_num => serial 79 | , waits => true 80 | , binds => binds 81 | , plan_stat => plans 82 | ); 83 | end; 84 | 85 | procedure client_on( 86 | client in varchar2 87 | , binds in boolean default false 88 | , plans in varchar2 default 'first_execution' 89 | ) as 90 | begin 91 | dbms_monitor.client_id_trace_enable( 92 | client_id => client 93 | , waits => true 94 | , binds => binds 95 | , plan_stat => plans 96 | ); 97 | end; 98 | 99 | procedure handle_on( 100 | service in varchar2 default sys_context('userenv','service_name') 101 | , module in varchar2 default all_modules 102 | , action in varchar2 default all_actions 103 | , binds in boolean default false 104 | , plans in varchar2 default 'first_execution' 105 | , instance in varchar2 default all_instances 106 | ) as 107 | begin 108 | dbms_monitor.serv_mod_act_trace_enable( 109 | service_name => service 110 | , module_name => module 111 | , action_name => action 112 | , waits => true 113 | , binds => binds 114 | , instance_name => instance 115 | , plan_stat => plans 116 | ); 117 | end; 118 | 119 | procedure database_on( 120 | binds in boolean default false 121 | , plans in varchar2 default 'first_execution' 122 | , instance in varchar2 default all_instances 123 | ) as 124 | begin 125 | dbms_monitor.database_trace_enable( 126 | waits => true 127 | , binds => binds 128 | , instance_name => instance 129 | , plan_stat => plans 130 | ); 131 | end; 132 | 133 | procedure session_off( 134 | sid in binary_integer default null 135 | , serial in binary_integer default null 136 | ) as 137 | begin 138 | dbms_monitor.session_trace_disable( 139 | session_id => sid 140 | , serial_num => serial 141 | ); 142 | end; 143 | 144 | procedure client_off( 145 | client in varchar2 146 | ) as 147 | begin 148 | dbms_monitor.client_id_trace_disable( 149 | client_id => client 150 | ); 151 | end; 152 | 153 | procedure handle_off( 154 | service in varchar2 default sys_context('userenv','service_name') 155 | , module in varchar2 default all_modules 156 | , action in varchar2 default all_actions 157 | , instance in varchar2 default all_instances 158 | ) as 159 | begin 160 | dbms_monitor.serv_mod_act_trace_disable( 161 | service_name => service 162 | , module_name => module 163 | , action_name => action 164 | , instance_name => instance 165 | ); 166 | end; 167 | 168 | procedure database_off( 169 | instance in varchar2 default all_instances 170 | ) as 171 | begin 172 | dbms_monitor.database_trace_disable( 173 | instance_name => instance 174 | ); 175 | end; 176 | 177 | end mrdba; 178 | / 179 | 180 | show errors 181 | 182 | 183 | -------------------------------------------------------------------------------- /code/sql/mr-packages/4-roles.sql: -------------------------------------------------------------------------------- 1 | -- create roles and users that a developer needs for tracing 2 | 3 | 4 | -- You must be SYSDBA to perform the required grants. 5 | connect sys/oracle@orcl as sysdba 6 | 7 | 8 | -- Create public synonyms for method_r.* packages. 9 | drop public synonym mrdev; 10 | create public synonym mrdev for method_r.mrdev; 11 | 12 | drop public synonym mrdba; 13 | create public synonym mrdba for method_r.mrdba; 14 | 15 | 16 | -- Create role "mr_developer_role", the Method R-endowed application developer. 17 | drop role mr_developer_role; -- Fresh start 18 | create role mr_developer_role; -- The Method R-endowed application developer 19 | grant execute on mrdev to mr_developer_role; -- Helpful tracing features 20 | 21 | -- We don't want to add the following privs, because the capabilities they 22 | -- enable are already offered by the MRDEV package. 23 | 24 | -- grant execute on sys.dbms_session to mr_developer_role; -- Required to use dbms_session 25 | -- grant execute on sys.dbms_application_info to mr_developer_role; -- Required to set Oracle user session handle attributes 26 | -- grant read on sys.v_$diag_info to mr_developer_role; -- Not required, but symmetrical 27 | -- grant read on sys.v_$diag_trace_file to mr_developer_role; -- Nice to have, but not used by any tracing-oracle scripts 28 | -- grant alter session to mr_developer_role; -- Required to use dbms_session.session_trace_enable (invoker's rights) 29 | 30 | grant read on sys.v_$diag_trace_file_contents to mr_developer_role; -- Required to read trace file content #TODO remove this when mr.mrdev.get_contents is done 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /code/sql/mr-packages/5-tests.sql: -------------------------------------------------------------------------------- 1 | -- test MR packages and privileges 2 | 3 | 4 | -- You must be SYSDBA to perform the required grants. 5 | connect sys/oracle@orcl as sysdba 6 | 7 | 8 | -- User DEV1 represents an application developer. 9 | drop user dev1 cascade; -- Fresh start 10 | create user dev1 identified by "Your-password-g0es-here"; -- An application developer 11 | grant create session to dev1; 12 | grant mr_developer_role to dev1; -- Endow the developer with Method R privileges 13 | 14 | -- User DBA1 represents a database administrator. 15 | drop user dba1 cascade; -- Fresh start 16 | create user dba1 identified by "Your-password-g0es-here"; -- A database administrator 17 | grant dba to dba1; -- A regular DBA 18 | grant execute on mrdev to dba1; -- The Method R developer toolkit 19 | grant execute on mrdba to dba1; -- The Method R DBA toolkit 20 | 21 | 22 | -- Developer testing 23 | connect dev1/Your-password-g0es-here 24 | 25 | -- Test the mrdev.set procedures. 26 | exec mrdev.set_module('my-module') 27 | exec mrdev.set_action('my-action') 28 | exec mrdev.set_client('my-client') 29 | 30 | -- Test the mrdev.get functions. 31 | set autoprint on 32 | var value varchar2(4000) 33 | exec :value := q'[service=']' || mrdev.get_service || q'[']' 34 | exec :value := q'[module=']' || mrdev.get_module || q'[']' 35 | exec :value := q'[action=']' || mrdev.get_action || q'[']' 36 | exec :value := q'[client=']' || mrdev.get_client || q'[']' 37 | exec :value := q'[filename=']' || mrdev.get_filename || q'[']' 38 | set autoprint off 39 | 40 | -- Test tracing. 41 | exec mrdev.trace_on 42 | col s new_value s 43 | select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') s from dual; -- Unique timestamp to validate trace file content 44 | select q'[The program I'm writing ran at &s]' message from dual; -- This is where your application being traced would go 45 | exec mrdev.trace_off 46 | set pagesize 500 47 | @my-trace-content -- #TODO delete this line when mrdev.get_content is written 48 | -- exec mrdev.get_content -- #TODO not written yet 49 | 50 | 51 | -- DBA testing 52 | connect dba1/Your-password-g0es-here 53 | 54 | -- Test trace enablers. 55 | @enabled-traces 56 | exec mrdba.handle_on(module=>'cary_module', action=>'cary_action'); 57 | @enabled-traces 58 | exec mrdba.handle_off(module=>'cary_module', action=>'cary_action'); 59 | @enabled-traces 60 | 61 | -- Test tracing. 62 | exec mrdba.session_on; 63 | col s new_value s 64 | select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') s from dual; -- Unique timestamp to validate trace file content 65 | select q'[The program I'm diagnosing ran at &s]' message from dual; -- This is where your application being traced would go 66 | exec mrdba.session_off; 67 | set pagesize 500 68 | @my-trace-content 69 | 70 | -------------------------------------------------------------------------------- /code/sql/mr-packages/make.sql: -------------------------------------------------------------------------------- 1 | -- make MR packages and privileges 2 | 3 | 4 | start 1-owner 5 | start 2-mrdev 6 | start 3-mrdba 7 | start 4-roles 8 | start 5-tests 9 | 10 | -------------------------------------------------------------------------------- /code/sql/my-handles.sql: -------------------------------------------------------------------------------- 1 | -- print my user session handle attribute values 2 | 3 | select sys_context('userenv', 'service_name') 4 | || '/' || sys_context('userenv', 'module') 5 | || '/' || sys_context('userenv', 'action') 6 | || '/' || sys_context('userenv', 'client_identifier') 7 | "SERVICE/MODULE/ACTION/CLIENTID" 8 | from 9 | dual 10 | / 11 | 12 | -------------------------------------------------------------------------------- /code/sql/my-trace-content.sql: -------------------------------------------------------------------------------- 1 | -- print my trace content 2 | 3 | -- Copyright (c) 2019, 2022 Method R Corporation 4 | 5 | select trim(trailing chr(10) from payload) "TRACE" 6 | from v$diag_trace_file_contents 7 | where adr_home || '/trace/' || trace_filename = ( 8 | select value from v$diag_info where name = 'Default Trace File' 9 | ) 10 | order by line_number 11 | / 12 | 13 | -------------------------------------------------------------------------------- /code/sql/my-trace-dir.sql: -------------------------------------------------------------------------------- 1 | -- print my trace directory name 2 | 3 | select value "TRACE DIRECTORY" from v$diag_info where name = 'Diag Trace'; 4 | 5 | -------------------------------------------------------------------------------- /code/sql/my-trace-file.sql: -------------------------------------------------------------------------------- 1 | -- print my trace file name 2 | 3 | select value "TRACE FILE" from v$diag_info where name = 'Default Trace File'; 4 | -------------------------------------------------------------------------------- /code/sql/my-trace-status.sql: -------------------------------------------------------------------------------- 1 | -- print info about my active traces 2 | 3 | select 4 | sid sid 5 | , serial# serial 6 | , service_name service 7 | , module module 8 | , action action 9 | , client_identifier clientid 10 | , sql_trace trace 11 | , sql_trace_waits waits 12 | , sql_trace_binds binds 13 | , sql_trace_plan_stats planstats 14 | from 15 | v$session 16 | where 17 | sid = sys_context('userenv','sid') 18 | / 19 | 20 | -------------------------------------------------------------------------------- /code/sql/trace-off.sql: -------------------------------------------------------------------------------- 1 | -- disable tracing for my session 2 | 3 | exec mrdev.trace_off 4 | 5 | 6 | -------------------------------------------------------------------------------- /code/sql/trace-on.sql: -------------------------------------------------------------------------------- 1 | -- enable tracing for my session 2 | 3 | exec mrdev.trace_on 4 | 5 | -------------------------------------------------------------------------------- /code/sql/trace-script.sql: -------------------------------------------------------------------------------- 1 | -- trace SCRIPT=&1 2 | 3 | -- Execute this from any tool capable of executing sqlplus scripts. 4 | -- Use it like this: 5 | -- 6 | -- SQL> @trace-script YOUR-SCRIPT.sql 7 | -- 8 | -- It will attempt to terminate the tool's session normally so the RDBMS can 9 | -- write critical end-of-trace information. 10 | 11 | @trace-on 12 | @&1 13 | exit 14 | 15 | -------------------------------------------------------------------------------- /code/sql/trace-username-off.sql: -------------------------------------------------------------------------------- 1 | -- disable tracing for all USERNAME=&1 sessions 2 | 3 | -- #TODO needs testing 4 | 5 | -- Copyright (c) 2019, 2022 Method R Corporation 6 | 7 | -- Stop tracing new sessions. 8 | alter trigger &1.trg_no_sys_logon disable; 9 | 10 | -- Disable tracing for all existing USERNAME sessions. 11 | begin 12 | for r in (select sid, serial# from v$session where type='USER' and username = '&1') loop 13 | dbms_monitor.session_trace_disable(r.sid, r.serial#); 14 | end loop; 15 | end; 16 | / 17 | 18 | -------------------------------------------------------------------------------- /code/sql/trace-username-on.sql: -------------------------------------------------------------------------------- 1 | -- enable tracing for all USERNAME=&1 sessions 2 | 3 | -- #TODO needs testing 4 | 5 | -- Copyright (c) 2019, 2022 Method R Corporation 6 | 7 | -- Enable tracing for any new USERNAME session. 8 | create or replace trigger &1.trg_no_sys_logon 9 | after logon on schema 10 | begin 11 | dbms_monitor.session_trace_enable; 12 | exception when others then null; 13 | end; 14 | / 15 | 16 | -- Enable tracing for all existing USERNAME sessions. 17 | begin 18 | for r in (select sid, serial# from v$session where type='USER' and username = '&1') loop 19 | dbms_monitor.session_trace_enable(r.sid, r.serial#); 20 | end loop; 21 | end; 22 | / 23 | 24 | -------------------------------------------------------------------------------- /code/sql/your-trace-file.sql: -------------------------------------------------------------------------------- 1 | -- print trace file name for SID=&1 2 | 3 | select tracefile from v$process where addr = (select paddr from v$session where sid=&1); 4 | 5 | -------------------------------------------------------------------------------- /code/vim/trc.vim: -------------------------------------------------------------------------------- 1 | " MacVim Syntax Highlighting for Oracle .trc files 2 | " Cary Millsap 3 | 4 | 5 | 6 | " Comments (lines whose first non-blank character is #) 7 | syntax match trcComment "^\s*#.*$" 8 | highlight link trcComment Comment 9 | 10 | " Numbers (matches whole numbers) 11 | syntax match trcNumber "\<\d\+\>" 12 | highlight link trcNumber Number 13 | 14 | " Database calls 15 | syntax match trcDbcall "PARSE\|EXEC\|FETCH" 16 | highlight link trcDbcall Identifier 17 | 18 | " System calls 19 | syntax match trcSyscall ": nam='.*'"hs=s+7,he=e-1 20 | highlight link trcSyscall Identifier 21 | 22 | " Cursor ID 23 | syntax match trcCursorID "\<\#\d\+\>" 24 | highlight link trcCursorID Identifier 25 | 26 | 27 | " #TODO 28 | " 29 | " To test this: 30 | " - Put a copy of this file (or a symlink) in ~/.vim/syntax. 31 | " - ":set filetype=trc" in the test .trc file. 32 | " 33 | " CursorID RE doesn't match yet. 34 | " ^PARSING IN CURSOR.*END OF STMT$ should be formatted like a constant. 35 | " Diminish the color of WAIT. 36 | " 37 | " https://superuser.com/questions/844004/creating-a-simple-vim-syntax-highlighting 38 | " 39 | " 40 | 41 | --------------------------------------------------------------------------------