By Brian Fitzgerald
Introduction
Given an Oracle RDS database, multiple application servers and multiple connections, the task at hand is to
- Create a logon trigger that will …
- Run when the first connection arrives and not again after that, and …
- Run trace 10046 …
- Up to 10 MB only.
- Identify the trace file
- Download the trace file
- Run tkprof
Background
- A logon trigger fires for every login that matches the firing condition. If we trace every session, we could file the file system. We only want one example trace file.
- In RDS, you do not have direct access to the operating system. You must somehow copy out the trace file.
Let’s go!
Grant
The first thing you need to get right is the grant. Trace requires “alter session” rights, which must be granted directly, not through a role. Suppose the user is “inuser”
grant alter session to inuser;
Create a sequence
create sequence inuser.user_trace_trg_seq;
Create the trigger
The trigger must be owned by the user that needs to be traced.
create or replace trigger inuser.user_trace_trg
after logon on database
when ( user = 'INUSER' )
declare
l_val number;
begin
l_val := inuser.user_trace_trg_seq.nextval;
if l_val = 1
then
execute immediate
q'{alter session set max_dump_file_size = '10m'}';
execute immediate
q'{alter session set tracefile_identifier = '}'||user||q'{_user_trace_trg'}';
execute immediate
q'{alter session set events '10046 trace name context forever, level 12'}';
end if;
end;
/
Now wait for the user to login. The first the trigger fires time, nextval equals 1, so the trigger body runs. After that, the trigger body does not run.
Identify the trace file
select * from table(
rdsadmin.rds_file_util.listdir('BDUMP')
)
where filename like '%INUSER_user_trace_trg.trc'
order by mtime;
| FILENAME | TYPE | FILESIZE | MTIME |
| ORCL_ora_9022_INUSER_user_trace_trg.trc | file | 10485856 | 2022-04-17 00:17:04 |
“Download” the trace file
You could transfer the file from rds to s3, and then from s3 to a local system. The other way is:
select text from table( rdsadmin.rds_file_util.read_text_file( :dir, :filename ) )
Using sqlalchemy and boto3, I have integrated this statement with AWS secrets manager in a convenient python script
$ download-rds-ora-dir-files.py --secret-id $sec --dir BDUMP --pat ORCL_ora_9022_INUSER_user_trace_trg.trc number of files: 1
You could also run sqlplus and spool the output to a file.
set feedback off
set linesize 32767
set trimspool on
set pagesize 0
set termout off
spool ORCL_ora_9022_INUSER_user_trace_trg.trc
select text from table(
rdsadmin.rds_file_util.read_text_file(
'BDUMP',
'ORCL_ora_9022_INUSER_user_trace_trg.trc'
)
)
;
Run tkprof
tkprof ORCL_ora_9022_INUSER_user_trace_trg.trc ORCL_ora_9022_INUSER_user_trace_trg.tkp
Done!
Conclusion
The following concepts were covered
- How to make a logon trigger body that runs only once.
- Permissions and object ownership for a logon trigger.
- How to download a trace file from RDS.