Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: January 22, 2003 - 7:43 am UTC

Last updated: November 15, 2006 - 6:54 am UTC

Version: 8.1.7

Viewed 10K+ times! This question is

You Asked

Tom,
Thank you for all the help you are doing?

We are running a EJB based application on a Oracle application server (9IAS) against an Oracle database (8.17). We have compliants from the application users about the application being slow sometimes. By the time the DBA goes to monitor the DB instance everything looks OK. We are unable to find out the exactly cause of the slowness. Every once in a while we come across inactive and orphan sessions. When I say Inactive session - these are the session that show up on TOPAS (AIX based) with Inactive status with connection time over 48 + hrs. Orphan sessions - session shows up on TOPAS doing nothing(most of the time with Inactive status and having a SQL associated). Orphan sessions stay on untill we kill them. When we look at the SQLs behind the inactive and orpahn sessions, they are simple SQLs that don't take much time to execute.
What might be causing the inactive and orphan sessions? Does it help to find out the background process associated with each of the inactive/orphan sessions?
Could missing 'close connection, close statement' be one of the problems?

Connections are made to the DB in MTS mode with connection pooling on the app server.
How do we find out if the connections from the app server are waiting for the DB to process the request? How do we find out if there are enough listner and dispatcher processes? Do the listner and dipatcher process show up on TOPAS?
How do I find out if the instance is working properly? ie. Is there enough SGA/PGA/UGA? Are there enough Oracle background processes running?

Thanks a lot in advance.


and Tom said...

Using MTS with connection pooling is a lot like using a cache to cache a cache (eg: it is overhead).

Since you can control the number of concurrent connections to the db via the connection pool -- it seems you would want dedicated server as MTS is by definition and design *slower* always then dedicated server. You use MTS when you can no longer get another connection via dedicated server cause the DB machine is way overloaded with processes.


My question to you is: did your developers instrument the code so they generate a log that shows you what the average response times for function X, Y or Z are? (doubt it, they never do until it is too later).

Have you run periodic TKPROFS (not really possible in MTS mode, need dedicated servers to make sense of that)

Do you collect statspack information for 15 minute peak windows (eg: 11am is busy every day so I would have a snapshot at 10:55 and 11:10 and maybe 11:30 and 11:45). It'll give you transaction rates, memory utilization, etc.




Rating

  (54 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Instrumenting the code

Tom, January 22, 2003 - 11:53 am UTC

You ask "did your developers instrument the code so they can generate a log?" Would this instrumentation be done in PL/SQL, and if so, what are your ideas for a best approach?

Tom Kyte
January 22, 2003 - 12:16 pm UTC

Yes, I do it all of the time in plsql -- for example, change the NO to YES in the above url and just watch what happens ;)


see also
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:6690299776039 <code>


I'm big into this (trace files, instrumentation, auditing).

Some people say "well, that logging code in my production code will just slow things down".

My response is "well, you wouldn't be talking to me if your production code wasn't slow - and yet here we are without any instrumentation and no clue as to where the performance issue is -- now what?"







Inactive sessions/Application slow

A reader, January 22, 2003 - 12:28 pm UTC


Now I know how Google works...

A reader, January 22, 2003 - 1:08 pm UTC

I always wondered where the Google engines get so accurate information.

Now I found out...

Goggle is nothing but a router to Ask Tom

;)

Now thats Groovy!

Jim, January 22, 2003 - 5:05 pm UTC

Tom,

Pretty slick!
Do you know of examples of books, articles that
I could reference to build something similar to
your site?

Regards
Jim

Tom Kyte
January 22, 2003 - 5:44 pm UTC

Very Interesting!

Robert, January 22, 2003 - 5:50 pm UTC

Tom,

I've done very little web stuff.. but that NO to YES thing is very nice.
Thanks for letting us have a peek into Tom's 'mind'!

Robert.

Jim, January 22, 2003 - 7:53 pm UTC

Tom,

Sorry my prior email should have said
I already found and read most of the discussions
re AskTom architecture, and have signed up with
Project Marvel.

I'll go checking the marvel site for more info
but I was hoping you might have suggestions
regarding info on building a site like yours


Cheers
Jim

Tom Kyte
January 23, 2003 - 7:42 am UTC

it was all built with marvel?? don't know what you mean I guess.

we designed a schema
we built API's

marvel did the UI...

Best way to debug

Tony, January 22, 2003 - 11:00 pm UTC

What is the best way to debug packages?
I hope your next book will have this topic also.


Tom Kyte
January 23, 2003 - 7:53 am UTC

there is jdeveloper which has a very nice debugger (if you need that sort of tool -- me, well, I haven't personally used a debugger since oh about 1990/1991)...


I instrument my code to generate trace files myself.

I use a tool we built called "debug" -- it is a package that lets us do tracing in various modules of code. it uses utl_file to write trace files on demand to the server.

It is documented fully in "beginning Oracle programming" where we used it as a case study.

You can get the source from www.wrox.com



Instrumenting he code

Subramanian, August 04, 2003 - 8:40 pm UTC

Tom,
Can we instrument the code by using
sys.dbms_system.ksdwrt(1,to_char(sysdate,'hh:mi:ss'));
This creates a trace file which is useful for finding out the response time of all the statements in a stored procedure.
Does it have any negative impact. Is it undocumented?
Thanks in advance.
Subramanian.

Tom Kyte
August 04, 2003 - 8:50 pm UTC

I would not, I would use utl_file (change would to "do") for os files and database tables for most stuff.... that is where I stick my trace information..

the problem with undocumented is -- well, it is undocumented. we have no clue as to the inner working in x.y.z vs x.y.a and can have NO expectations either.

i know that api

i've never used it.

debug/audit information

A reader, August 25, 2003 - 8:47 pm UTC

Hi tom
1. Do you have some kind of purging policy on your
auditing table? I am imagining that while developing and
testing we would end up inserting a lot of data.

Even in production, how do you take care of these
tables from becoming too large?
2. In my case, I am trying to implement a similar flag
in URL. I use dbms_output.put_line in the plsql
procedure and then use DbmsOutput.java to get it
and show it through my servlet. I am encountering
a strange issue. Sometime my entire set of messages
is repeated as shown below:
debug msg1
debug msg2

debug msg1
debug msg2


I debugged through and noticed that the show()
procedure of DbmsOutput.java sometimes returns
duplicate message. Looking at the select
statement that you defined - do you see any bug
off the top of your head:
m_showStatement = conn.prepareCall(
"declare " +
" l_line varchar2(255); " +
" l_done number; " +
" l_buffer long; " +
"begin " +
" loop " +
" exit when length(l_buffer)+255 > :maxbytes OR l_done = 1; " +
" dbms_output.get_line( l_line, l_done ); " +
" l_buffer := l_buffer || l_line || chr(10); " +
" end loop; " +
" :done := l_done; " +
" :buffer := l_buffer; " +
"end;" );

Thanx a lot!!!

Tom Kyte
August 26, 2003 - 8:37 am UTC

1) we "roll them"...

you can either do this with partitioning.... every month, add a new partition on the end for next months data, drop/archive the oldest.

if you don't have partitioning, you can use synonyms and views. every month, create a new table, repoint the synonym (so the inserts go there) and have a view that is a union all of the relevant tables you want in your audit trail.


I use both, partitioning is more effective/efficient

2) it most likely means you are maintaining a connection pool, this pool is NOT reseting the package state, so you are getting debug from not just your session but others who are running it as well (but not dumping the output)

Thanx Tom!

A reader, August 26, 2003 - 10:21 am UTC

"2) it most likely means you are maintaining a connection pool, this pool is NOT
reseting the package state, so you are getting debug from not just your session
but others who are running it as well (but not dumping the output) "

Hmmmm..You are right! I am maintaining the
connection pool - but I am the only one who is executing
this code (since it is development - and the particular
page is new)

However, this rules out my using the DbmsOuput.java
for the purpose of "debug" flag in URL :(
I can try and use the my_dbms_output as defined
by you. However, it would be tough to convince
others to use a "non-standardad" package.

So when you convert the flag fro NO to YES
in asktom, do you get the info from a table?
In that case is not that too much data?
O I guess you just use plsql package to conditionally
generate the data - of course!:)

Any suggestions what I should do (plsql based
UI is not an option for me)

Regards



Tom Kyte
August 26, 2003 - 10:54 am UTC

try debug.f maybe?

</code> http://asktom.oracle.com/~tkyte/debugf <code>

my_dbms_output

A reader, August 26, 2003 - 10:44 am UTC

I realized that my_dbms_output will also have the
same problem.

How about modifying your debug.f to populate a global
temporary table with the debug data. So for
each page.
1. In the plsql that gets invoked by the page
I would have debug.f() that puts data in a global
temporary table (instead of a file) (the GTT will
have all the debug related columns such as
Time stamp, line number etc (using the debug.f)
functionality.
2. In the page, if the url's debug flag is open, I would
do a select from this global temporary table. At the
beginning of each page - I will have to delete
the data from gtt (so that I don't see accumulated
debug info from previous pages in the same session.

Do you see any problems with this approach, given I am
using connection pools?

Thanx!

Tom Kyte
August 26, 2003 - 11:00 am UTC

do you use plsql in your applications? if so, you might consider a call to dbms_session.reset_package_state to avoid these issues alltogether.

else user1 will get user2's packge state, which could be a problem


thanx Tom!

A reader, August 26, 2003 - 11:12 am UTC

"do you use plsql in your applications? if so, you might consider a call to
dbms_session.reset_package_state to avoid these issues alltogether."

Yes we use plsql - all my dmls are in plsql.
However, for UI we don't use plsql.

I suppose you meant dbms_session.reset_package?
I don;t think I can use it on each url (at the beginning)
because it could have side effects? Also, I am not sure
if it is the package state that is causing the problem
since I am the only one accessing the application
and the database (and getting the duplicate debug messages)

What do you think of my GTT based solution?

Thank you so much!



Tom Kyte
August 26, 2003 - 11:25 am UTC

if you are using a connection pool

and you use packages

and you don't call it - -you'll REALLY have side effects.


user 1 grabs connection A
uses a package, sets some variables
user 1 gives up connection A
user 2 gets connection A -- bummer.

Thanx!

A reader, August 26, 2003 - 11:41 am UTC

"if you are using a connection pool
and you use packages
and you don't call it - -you'll REALLY have side effects.
..."

Actually, I am not sure whether we are doing that or not.
I will ask the guys who are responsible for managing the
connection pool to do it.
So this has to be done just before you hand over the
connection (e.g. in the connection.getConnection() )
method, I suppose?

Assuming that that is not the problem:) (- will verify
if that is the case by asking the right folks), could
you please comment on the GTT solution. I am trying it
out as we speak..
1. I delete all the messages from the GTT at the begining
of the rendering of a url
2. I use debug.f (that also inserts into gtt now
3. I use a simple select from this GTT to display message
if the url indicates that the debug is on.


Tom Kyte
August 26, 2003 - 1:32 pm UTC

that'll work, sure -- it'll be just like resetting the package state :)

hi tom

A reader, August 26, 2003 - 1:53 pm UTC

"that'll work, sure -- it'll be just like resetting the package state "

But from the doc, it seems that resetting a package state
would free ALL package states - not just the one that
I am executing. GTT does not have this issue, I think.
Only the debug messages associated with procedures that are invoked during the rendering of the URL will
be deleted.

btw, it seems to work fine and I don't seem to be getting
multiple debug messages anymore..

Thanx!




"DBMS_SESSION.RESET_PACKAGE;
..
This procedure deinstantiates all packages in this session: It frees **all** package states.
Memory used for caching execution state is associated with all PL/SQL functions,
procedures, and packages that have been run in a session.
For packages, this collection of memory holds the current values of package
variables and controls the cache of cursors opened by the respective PL/SQL
programs. A call to RESET_PACKAGE frees the memory associated with each of the
previously run PL/SQL programs from the session, and, consequently, clears the
current values of any package globals and closes any cached cursors.
RESET_PACKAGE can also be used to reliably restart a failed program in a session. If
a program containing package variables fails, then it is hard to determine which
variables need to be reinitialized. RESET_PACKAGE guarantees that all package
variables are reset to their initial values."

Tom Kyte
August 27, 2003 - 7:46 am UTC

you *need* to reset the package states. anything short of that would be what is known as "a bug"


there is 0% chance you want user2 to have user1's package state.

it is not an issue -- it is a feature.

one doubt about debug.f

A reader, August 26, 2003 - 9:01 pm UTC

It seems it does not have a way to turn off
all work by flipping flag (e.g. an enable/disable switch)
I can see it has debug.clear() - but when you say debug.f()
it still goes through all the selects (they don't return
anything.. Anyways, do you think this could be a good
feature. I plan to add it but wanted to ask you since
I maybe missing something. So what I want is (pseudo code)
debug.f()
{
if ( debug.enable) then
do whatever
end if
}

Thank you!!!

Tom Kyte
August 27, 2003 - 8:00 am UTC

sure, sounds like a great idea.

debug.f enhancements

A reader, August 27, 2003 - 12:21 pm UTC

So, I already enhanced the debug.f to use temporary
table to store and retrieve debug messages alongwith
the option of putting the info in a trace file.
It seems to work well.

Now I plan to add the "enable" flag. I have doubts on
how to make this work.

In my case, as I said, I don't use plsql to generate
pages. So this is what my pseudo code from the url
looks like:
1.If debug is on in URL, I call an init to initialize
the debug variables - this could set a package level
variable for that session (or a temporary table) to
YES.
2. I do my processing - some of the processing involves
calling plsql procedures with dml statements that
return results to be displayed in the GUI. I intersperse
them with debug.f messages. In my case, I have enhanced
the method to put them in a temporary table (apart from
putting them in the file)
3. I use a util method to get the data from the temporary
table - I have the option of get_debug_info and
get_Debug_info_flush (the second one deletes data
after getting them from the temporary table)
Now if the debug url was set to NO, with the new
enhancement of the "enable" flag in debug, I would
not incur any penalty of selects etc being done by the
debug.f method.

Should I use a package variable or a temporary table.
Actually, as I type this in, I am thinking of a
package variable - here I don't have the doubts of
resetting of package variables - as I would be setting
this value to ON before every URL rendering begins
IF the debug is ON.

Any thoughts ( I am using connection pooling)?

Also, I have following doubts:
1. I am still not clear on *when* to use the
dbms_session.reset_package;
Since I use connection pooling, I am thinking we
should do it in the connectionPool.getConnection()
method. However, how does this work because in
connection pool during one transaction itself
I can grab the connection many times.

Say, in the same session, I am doing for a UI
initiated process doSomethingFromUI - I do the
following steps.
a. grab connection - do processing 1
b. grab connection - do processing 2

In steps a and b, I may get different connections - does
this imply that in 1 and two I should not be relying
on any package state - This does not make sense -
what am I missing or misunderstanding here!

2. should I send my enhancements to Christopher or post
it here?

Thanx!!




Tom Kyte
August 27, 2003 - 6:03 pm UTC

1) you should clear it when you give the connection back for the last time OR when you grab it for the first time.

why would you grab two different connections for a single page -- doesn't seem to make sense -- you would lose the temp table from session1 in session2 and vice versa.


2) you can post it here if you like.

one more question

A reader, August 27, 2003 - 12:26 pm UTC

To the previous questions, please add this one
3. For the debug.f file - if we don;t have the utl_file_dir
directory enabled by default in our app, how do we
deal with this. I was thinking of using "create directory"
but for each install we need a starting point (as the
absolute path would be different in different machines).
How do we solve this issue?

Thanx!

Tom Kyte
August 27, 2003 - 6:03 pm UTC

3) up to you -- to use utl_file, you need utl_file_dir. or if you have 9i, you can use a directory object which must be created. thats about it.

thanx Tom!

A reader, August 27, 2003 - 6:33 pm UTC

"1) you should clear it when you give the connection back for the last time OR
when you grab it for the first time.

why would you grab two different connections for a single page -- doesn't seem
to make sense -- you would lose the temp table from session1 in session2 and
vice versa."

You are right - when I thought a little more, I realized
I don't do that. - I get it only once per rendering of the
page.
So if I have a URL - then while rendering I grabbed
the connection once. If there is a button on a url
that changes something - then again I grabbed the
connection (Second time)and rerendered the URL with the
connection (may be a different one) Is this scenario
wrong? (Every event initiated by URL that requires db
access gets a connection from the pool.)

hmm... I think I am a little confused on the the connection
thinggy versus session. Each connection I guess represents
a session (assuming dedicated server), right? There is
a one to one relationship between them, right?
Also, a global package variable - when set is set for
that session only - if some other session sets it
it gets its own copy, right?

2) you can post it here if you like.
I will
Now for the 3rd response from you
"3) up to you -- to use utl_file, you need utl_file_dir. or if you have 9i, you
can use a directory object which must be created. thats about it.
"

I was thinking of creating a directory. But this directory
"root" would be different in every database.
When you install the application - somewhere you would
run "CREATE DIRECTORY admin AS Â’oracle/adminÂ’;"

You don't want to hard code that path to avoid editing the
directory again and again - you want to specify a relative path. Is their any way? I hope I am clear in my question.

Thank you!!

Tom Kyte
August 27, 2003 - 7:27 pm UTC

each connection represents an oracle session yes.

when you grab a connection, you are grabbing someone elses pre-existing system, and inherit whatever they had (with most connection pools anyway)

relative path to WHAT ? relative to where??

A reader, August 27, 2003 - 7:57 pm UTC

"relative path to WHAT ? relative to where?? "

Basically, I want to avoid hard coding the path
because it would be different in each install and
I dont want to edit the install script to just change
the directory - so for example, I could create a path
to the Oracle home (but how do I get that in sql)?

Tom Kyte
August 28, 2003 - 7:41 am UTC

i would use either of background dump dest or user dump dest as a destination.

or prompt the user for the location.

thanx!

A reader, August 28, 2003 - 10:22 am UTC

the idea of using bdump is a good one!

debug.f

A reader, August 28, 2003 - 11:28 am UTC

Hi Tom,
Can you please put the link
</code> http://asktom.oracle.com/~tkyte/debugf <code>

in your page
"Click here for tidbits, howtos and archived presentations "

Thanks!

Tom Kyte
August 29, 2003 - 7:46 am UTC

done

here is the modified debug.f - please give your comments

A reader, August 28, 2003 - 1:33 pm UTC

Wish I could make things bold in my response instead
of simple text ( to highlight changes)

Features added:

F1. It has a flag to enable and disable debugging.
The flag take on following values (int constants)
a. DEBUG_OFF - This means that debugging code for
debug.f() and debug.fa() would just return
without doing anything.
b. DUMP_FOR_URL_ONLY - enable debugging so that you
see the output only in the URL displayed -
*DON'T* do any trace file generation in the trace
file directory.
c. DUMP_IN_TRACE_FILES_ONLY
enable debugging so that you see the output only in
the trace file directory - no need to display the
output in the URL.
d. DUMP_FOR_TRACE_FILES_AND_URL
enable debugging so that you see the output the
trace file as well as on the URL.

To disable debugging execute
debug.disable;

To enable debugging (e.g. for trace files and URL)
execute
debug.enable ( DUMP_FOR_TRACE_FILES_AND_URL );

For URL based dumping (which is not htp.p based),
you can do the following

1. Before URL based generation code begins check
to see from the URL page property if debug flag
is on.
2. If the flag is off don't do anything
3. If the flag is on, execute debug.enable (
valid_debug_flag)
4. continue processing URL generation code - this
could involve plsql code calls that have been
instrumented using debug.f.
5. if debug_flag is enabled for URL display
execute debug.get_debug_info_flush to get
the data and flush the temporary table where
it gets stored.
6. execute debug.disable (this is to reset the
package variable)

F2. If debug is not set to off then the output is
always shown using dbms_output.put_line. This is
useful for sql prompt based debugging which is
what many people are used to.


Note: I added a temporary table to store messages
to be displayed in URL.

-----------------------debug.sql starts -----------
---- also contains schema required to make it work
---------------------------------------------------
set echo off

create or replace
type Argv as
table of varchar2(4000);
/

create global temporary table debug_info
(
message varchar2(4000)
)
on commit delete rows;
/
create table debugTab(
userid varchar2(30) primary key,
modules varchar2(4000),
locat varchar2(4000),
filename varchar2(4000)
)
/

create or replace
trigger bi_fer_debugtab
before insert on debugtab for each row
begin
:new.modules := upper( :new.modules );
end;
/

create or replace
package debug as
--
-- version 1.0
-- clbeck - 13-OCT-98 - Initial version
--
-- PACKAGE TO DUMP DEBUG INFORMATION OF PL/SQL ROUTINE
-- TO A FILE DURING EXECUTION
--
--
-- This package allows the developer to selectively produce debug
-- information for pl/sql process.
--
-- Setup:
-- Make sure the utl_file_dir paramter is assigned in the init.ora
-- file. You need an entry for each dir that you want to be able to
-- write to.
-- eg.
-- utl_file_dir = /tmp
-- utl_file_dir = /home/clbeck/sql/debug
--
-- Usage:
-- There are two procedure to write debug information ( f and fa ).
-- Anywhere in your code that you want to print debug information use:
--
-- debug.f( 'Expected %s bytes, got %s bytes', l_expect, l_got );
--
-- This will replace the the first %s with the value of l_expect and the
-- second %s with the value of l_got.
--
-- If you have more than 10 %s in your string then you will need to use the fa
-- procedure like:
--
-- debug.fa( 'List: %s,%s,%s,%s,%s,%s',
-- argv( 1, 2, l_num, 'Chris', l_cnt, 10 ) );
--
-- Runtime:
-- To enable the debug run:
--
-- debug.init( 'myProc' );
-- debug.enable ( <a valid debug flag other than debug.DEBUG_OFF> )
--
-- This will cause only debug for the procedure/package named
-- myProc to be generated.
-- All other debug statements will generate no output.
-- To debug all procedures/packages,
-- set p_modules = 'ALL';
--
-- NOTE:
-- If debug is not set to off then the output is
-- always shown using dbms_output.put_line. This is
-- useful for sql prompt based debugging which is
-- what many people are used to.
--
-- To stop debug run:
--
-- debug.clear;
--
-- To disable debug run
--
-- debug.disable;
--
-- To get debug message outputted for a URL generation do the following:
--
-- For URL based dumping (which is not htp.p based),
-- you can do the following

-- 1. Before URL based generation code begins check
-- to see from the URL page property if debug flag
-- is on.
-- 2. If the flag is off don't do anything
-- 3. If the flag is on, execute debug.enable (
-- valid_debug_flag)
-- 4. continue processing URL generation code - this
-- could involve plsql code calls that have been
-- instrumented using debug.f.
-- 5. if debug_flag is enabled for URL display
-- execute debug.get_debug_info_flush to get
-- the data and flush the temporary table where
-- it gets stored.
-- 6. execute debug.disable (this is to reset the
-- package variable)
--
-- Output:
-- The output looks like:
--
-- 981013 130530 (CLBECK.MYPROC, 221) this is my debug output
-- ^^^^^^ ^^^^^^ ^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- date time owner.proc lineno message
--
--
-- Enhancements and Bugs:
--
-- Send all enhancements requests and bugs to me,
-- Christopher Beck (clbeck@us.oracle.com)
--
--

g_dir_locat constant varchar2(4000) := '/tmp';

-- following constants determine where all the debugging messages
-- are output. Please note that if the DEBUG_OFF is NOT used then
-- regardless of the output option chosen, the message is output
-- on the sqlplus screen using dbms_output.put_line.

DEBUG_OFF constant int := 0; -- no debugging messages output to
-- any destination
DUMP_FOR_URL_ONLY constant int := 1; -- only for URL based debugging
DUMP_IN_TRACE_FILES_ONLY constant int := 2; --dump only in trace files
DUMP_FOR_TRACE_FILES_AND_URL constant int := 3; -- both in URL and trace files

emptyDebugArgv Argv;

--
-- Initializes the debuging for specified p_modules and will dump the
-- output to the p_dir directory on the server for the user p_user.
--
procedure init(
p_modules in varchar2 default 'ALL',
p_dir in varchar2 default g_dir_locat,
p_file in varchar2 default null,
p_user in varchar2 default user );

procedure f(
p_message in varchar2,
p_arg1 in varchar2 default null,
p_arg2 in varchar2 default null,
p_arg3 in varchar2 default null,
p_arg4 in varchar2 default null,
p_arg5 in varchar2 default null,
p_arg6 in varchar2 default null,
p_arg7 in varchar2 default null,
p_arg8 in varchar2 default null,
p_arg9 in varchar2 default null,
p_arg10 in varchar2 default null );

procedure fa(
p_message in varchar2,
p_args in Argv default emptyDebugArgv );

procedure clear(
p_user in varchar2 default user );

--
-- Returns the current status of debugging for the user p_user.
--
procedure status(
p_user in varchar2 default user,
p_modules out varchar2,
p_file out varchar2,
p_dir out varchar2 );

--
-- deletes info from the temporary table (useful for flushing the
-- messages already seen in a URL based debugging
--
procedure delete_debug_info;

--
-- enables debugging
-- messages already seen in a URL based debugging
-- The p_debug_flag can take on following values (int constants)
-- 1. DEBUG_OFF - This means that debugging code for
-- debug.f() and debug.fa() would just return
-- without doing anything.
-- 2. DUMP_FOR_URL_ONLY - enable debugging so that you
-- see the output only in the URL displayed -
-- *DON'T* do any trace file generation in the trace
-- file directory.
-- 3. DUMP_IN_TRACE_FILES_ONLY
-- enable debugging so that you see the output only in
-- the trace file directory - no need to display the
-- output in the URL.
-- 4. DUMP_FOR_TRACE_FILES_AND_URL
-- enable debugging so that you see the output the
-- trace file as well as on the URL.
--
procedure enable ( p_debug_flag int );

-- disables debugging
-- Used to incur minimal performance penalty for instrumenting
-- the code with debug.f() and debug.fa()

procedure disable;

-- gets debug messages from the temporary table (for url based
-- debugging - to display the debug messages on the URL just
-- the asktom.oracle.com does if you flip the "NO" in an article's
-- URL to "YES")

function get_debug_info return sys_refcursor;

-- gets debug messages from the temporary table and deletes
-- that info from the temporary table ( useful for url based
-- debugging - to display the debug messages on the URL just
-- the asktom.oracle.com does if you flip the "NO" in an article's
-- URL to "YES") Typically you want to see the same message again in
-- the URL - so this method deletes after returning a cursor
-- containing debug messages

function get_debug_info_flush return sys_refcursor;

end debug;
/

show error

grant execute on debug to public
/

create or replace
package body debug as

--g_enable_flag int default DEBUG_OFF;
g_enable_flag int default DEBUG_OFF;
g_owner varchar2(2000);
g_name varchar2(2000);
g_lineno number;
g_caller_t varchar2(2000);

g_file varchar2(2000);

procedure init(
p_modules in varchar2 default 'ALL',
p_dir in varchar2 default g_dir_locat,
p_file in varchar2 default null,
p_user in varchar2 default user ) is
--
r debugTab%rowtype;
begin
clear( p_user );
insert into debugTab values ( p_user, p_modules, p_dir, p_file );
end init;


procedure clear( p_user varchar2 default user ) is
begin
delete from debugTab where userid = p_user;
end clear;


procedure status(
p_user in varchar2 default user,
p_modules out varchar2,
p_file out varchar2,
p_dir out varchar2 ) is
begin
select modules, locat, filename
into p_modules, p_dir, p_file
from debugTab
where userid = p_user;
exception
when NO_DATA_FOUND then
p_modules := null;
p_dir := null;
p_file := null;
end status;

procedure who_called_me(
owner out varchar2,
name out varchar2,
lineno out number,
caller_t out varchar2 ) is
--
call_stack varchar2(4096) default dbms_utility.format_call_stack;
n number;
found_stack BOOLEAN default FALSE;
line varchar2(255);
cnt number := 0;
begin
loop
n := instr( call_stack, chr(10) );
exit when ( cnt = 3 or n is NULL or n = 0 );
--
line := substr( call_stack, 1, n-1 );
call_stack := substr( call_stack, n+1 );
--
if not found_stack then
if line like '%handle%number%name%' then
found_stack := TRUE;
end if;
else
cnt := cnt + 1;
-- cnt = 1 is ME
-- cnt = 2 is MY Caller
-- cnt = 3 is Their Caller
if ( cnt = 3 ) then
lineno := to_number(substr( line, 13, 6 ));
line := substr( line, 21 );
if ( line like 'pr%' ) then
n := length( 'procedure ' );
elsif ( line like 'fun%' ) then
n := length( 'function ' );
elsif ( line like 'package body%' ) then
n := length( 'package body ' );
elsif ( line like 'pack%' ) then
n := length( 'package ' );
else
n := length( 'anonymous block ' );
end if;
caller_t := ltrim(rtrim(upper(substr( line, 1, n-1 ))));
line := substr( line, n );
n := instr( line, '.' );
owner := ltrim(rtrim(substr( line, 1, n-1 )));
name := ltrim(rtrim(substr( line, n+1 )));
end if;
end if;
end loop;
end who_called_me;

function is_number( n varchar2 ) return boolean is
begin
if n between '0' and '9' then
return true;
end if;
return false;
end is_number;

function parse_it(
p_message in varchar2,
p_args in argv default emptyDebugArgv ) return varchar2 is
--
l_tmp long := p_message;
l_str long := null;
l_idx number;

l_numstr1 varchar2(10);
l_numstr2 varchar2(10);

l_tmp1 long;
l_str1 long;

l_num number;
l_char long;
begin

for i in 1 .. p_args.count loop
l_idx := instr( l_tmp, '%' ) ;
exit when nvl(l_idx,0) = 0;

l_str := l_str || substr( l_tmp, 1, l_idx-1 );
l_tmp := substr( l_tmp, l_idx+1 );

if substr( l_tmp, 1, 1 ) = 's' or
substr( l_tmp, 1, 1 ) = 'd' then
l_str := l_str || p_args(i);
l_tmp := substr( l_tmp, 2 );
elsif is_number( substr( l_tmp, 1, 1 ) ) or
substr( l_tmp, 1, 1 ) = '.' then

l_numstr1 := null;
l_numstr2 := null;

l_tmp1 := l_tmp;
l_str1 := l_str;

loop
exit when not is_number( substr( l_tmp1, 1, 1 ) );
l_numstr1 := l_numstr1 || substr( l_tmp1, 1, 1 );
l_tmp1 := substr( l_tmp1, 2 );
end loop;

if substr( l_tmp1, 1, 1 ) = '.' then
l_tmp1 := substr( l_tmp1, 2 );
if is_number( substr( l_tmp1, 1, 1 ) ) then
loop
exit when not is_number( substr( l_tmp1, 1, 1 ) );
l_numstr2 := l_numstr2 || substr( l_tmp1, 1, 1 );
l_tmp1 := substr( l_tmp1, 2 );
end loop;
else
l_tmp1 := '!' || l_tmp1;
end if;
end if;

begin
if substr( l_tmp1, 1, 1 ) = 's' then
l_tmp := substr( l_tmp1, 2 );
if l_numstr2 is null then
l_tmp1 := p_args(i);
else
l_tmp1 := substr( p_args(i), 1, l_numstr2 );
end if;
if l_numstr1 is not null then
l_tmp1 := lpad( l_tmp1, l_numstr1 );
end if;
l_str := l_str1 || l_tmp1;
elsif substr( l_tmp1, 1, 1 ) = 'd' then
l_tmp := substr( l_tmp1, 2 );
if l_numstr1 is null then
l_tmp1 := lpad( '9', 39, '9' );
else
l_tmp1 := lpad( '9', l_numstr1, '9' );
end if;
if l_numstr2 is not null then
l_tmp1 := substr( l_tmp1, 1, l_numstr1-l_numstr2 ) || '.' ||
substr( l_tmp1, -l_numstr2 );
end if;
l_str := l_str1 || to_char( to_number( p_args(i) ), l_tmp1 );
else
l_str := l_str || '%';
end if;
exception
when others then
l_str := l_str1 || 'XXXXXXXXXX';
end;

else
l_str := l_str || '%';
end if;

end loop;

return l_str || l_tmp;

exception
when others then
return l_str || l_tmp;
end parse_it;


procedure internal_f(
p_message in varchar2,
p_args in Argv default emptyDebugArgv ) is
--
l_locat varchar2(4000);
l_modules varchar2(4000);
l_filename varchar2(4000);
l_message long := null;
l_final_message long;
l_file utl_file.file_type;
l_date varchar2(255);
begin

select modules, locat, filename, to_char( sysdate, 'YYMMDD HH24MISS' )
into l_modules, l_locat, l_filename, l_date
from debugTab
where userid = user;

if instr( l_modules, nvl(g_name,'BLAH') ) = 0 and
l_modules <> 'ALL' then
return;
end if;

if l_filename is not null then
g_file := l_filename;
end if;

l_message := parse_it( p_message, p_args );
/*
l_message := p_message;

begin
for i in 1 .. p_args.count loop
if instr( l_message, '%s' ) = 0 then
exit;
else
l_message := substr( l_message, 1, instr( l_message, '%s' )-1 ) ||
p_args(i) ||
substr( l_message, instr( l_message, '%s' )+2 );
end if;
end loop;
exception
when others then
null;
end;
*/

l_message := replace( l_message, '\n', chr(10) );
l_message := replace( l_message, '\t', chr(9) );

if( g_enable_flag = DUMP_IN_TRACE_FILES_ONLY or
g_enable_flag = DUMP_FOR_TRACE_FILES_AND_URL ) then
l_file := utl_file.fopen( l_locat, g_file, 'a', 32767 );
if not utl_file.is_open( l_file ) then
dbms_output.put_line( 'File not opened' );
end if;
end if;

if g_owner is null then
g_owner := user;
g_name := 'ANONYMOUS BLOCK';
end if;

l_final_message := l_date ||
' (' || lpad( g_owner || '.' || g_name, 20 ) || ',' ||
lpad(g_lineno,4) || ') ' || l_message;

if( g_enable_flag = DUMP_IN_TRACE_FILES_ONLY or
g_enable_flag = DUMP_FOR_TRACE_FILES_AND_URL ) then

utl_file.put( l_file, '' );
utl_file.put_line( l_file, l_final_message );
utl_file.fclose( l_file );
end if;
if( g_enable_flag = DUMP_FOR_URL_ONLY or
g_enable_flag = DUMP_FOR_TRACE_FILES_AND_URL ) then
insert into debug_info ( message) values ( l_final_message );
end if;

-- regardless of debug flags - always show it using the
-- dbms_output.put_line for sqlplus based debugging.

dbms_output.put_line ( l_final_message );
exception
when NO_DATA_FOUND then
-- dbms_output.put_line( sqlerrm );
null;
end internal_f;


procedure fa(
p_message in varchar2,
p_args in Argv default emptyDebugArgv ) is
begin
if( g_enable_flag = DEBUG_OFF ) then
return;
end if;
who_called_me( g_owner, g_name, g_lineno, g_caller_t );
internal_f( p_message, p_args );
end fa;


procedure f(
p_message in varchar2,
p_arg1 in varchar2 default null,
p_arg2 in varchar2 default null,
p_arg3 in varchar2 default null,
p_arg4 in varchar2 default null,
p_arg5 in varchar2 default null,
p_arg6 in varchar2 default null,
p_arg7 in varchar2 default null,
p_arg8 in varchar2 default null,
p_arg9 in varchar2 default null,
p_arg10 in varchar2 default null ) is
begin
if( g_enable_flag = DEBUG_OFF ) then
return;
end if;
who_called_me( g_owner, g_name, g_lineno, g_caller_t );
internal_f( p_message,
argv( substr( p_arg1, 1, 4000 ),
substr( p_arg2, 1, 4000 ),
substr( p_arg3, 1, 4000 ),
substr( p_arg4, 1, 4000 ),
substr( p_arg5, 1, 4000 ),
substr( p_arg6, 1, 4000 ),
substr( p_arg7, 1, 4000 ),
substr( p_arg8, 1, 4000 ),
substr( p_arg9, 1, 4000 ),
substr( p_arg10, 1, 4000 ) ) );
end f;

procedure delete_debug_info is
begin
delete debug_info;
end delete_debug_info;

procedure enable ( p_debug_flag int) is
begin
if( p_debug_flag = DUMP_FOR_URL_ONLY or
p_debug_flag = DUMP_IN_TRACE_FILES_ONLY or
p_debug_flag = DUMP_FOR_TRACE_FILES_AND_URL ) then
g_enable_flag := p_debug_flag;
end if;
end enable;

procedure disable is
begin
g_enable_flag := DEBUG_OFF;
end disable;

function get_debug_info return sys_refcursor is
l_cursor sys_refcursor;
begin
open l_cursor for
select message
from debug_info;
return l_cursor;
end get_debug_info;

function get_debug_info_flush return sys_refcursor is
l_cursor sys_refcursor;
begin
l_cursor := get_debug_info;
delete_debug_info;
return l_cursor;
end get_debug_info_flush;

begin

g_file := 'DEBUGF_'||userenv('SESSIONID');

end debug;
/
show errors
/

-----------------------debug.sql ends -----------



Why slow database becomes normal after restarting

A reader, October 10, 2003 - 5:59 pm UTC

Hi Tom,

My database runs slower and slower after time goes by, however it becomes fast if I restart it.

Is it possible that I can "reset" the database status without restarting it?

Such as:

Reset shared pool
Reset buffer cache
Reset PGA

Tom Kyte
October 10, 2003 - 6:17 pm UTC

maybe it was tired and needed a nap!

Seriously -- there is so little quantative information here that no one can say anything....

no OS's
no version's
no description of what "slow" means and how fast is "fast"
no clue as to how long this takes to get like this (a day, a week, a year)
no diagnostic information like "we notice that process X grew from A bytes to B bytes and keeps growing, the disk lights are constantly on after a while" or anything...


You need to find the CAUSE (eg: maybe statspack taken in 15 minute windows, over time can be used to see what waits increase over time) (eg: maybe an os tool can detect some sort of leak, showing you -- ah hah, the system starts swapping/paging like mad because process foo grew to X million gigabytes)

Then and only then can one say something.....

A reader, October 11, 2003 - 8:01 am UTC


Tom Kyte
October 11, 2003 - 10:27 am UTC

thats about the same way i felt about the above "review" myself ;)

Inactive sessions

A reader, October 20, 2003 - 1:44 am UTC

Tom,
We are coming across inactive db sessions with associated SQLs.  We are not sure why these inactive sessions are showing up.  

The application is an EJB based application.
My questions are
1) Is it normal to have inactive sessions with SQLs associated(even after the session is idle for 14 + hrs)?
2) Do such session lead to blocked sessions?

Thank you


SQL>     SELECT    TO_CHAR(SYSDATE, 'dd Mon yyyy hh24:mi:ss')     AS "System Time"
  2         FROM dual
  3  /

System Time                                                                     
--------------------                                                            
17 Oct 2003 08:42:42                                                            

SQL>     SELECT    SUBSTR(p.spid, 1, 7)                 AS process
  2            , TO_CHAR(s.logon_time, 'dd Mon yyyy hh24:mi:ss')  AS logon
  3            , TO_CHAR(s.sid, '999')                 AS sid
  4            , TO_CHAR(s.serial#, '99999')             AS serial
  5            , SUBSTR(s.status, 1, 3)                 AS act
  6            , SUBSTR(s.server, 1, 3)                 AS srv
  7            , SUBSTR(s.username, 1, 16)             AS user_name
  8            , LPAD
  9             ( TO_CHAR( FLOOR( s.last_call_et / ( 3600 * 24 ) ), 'FM999' )
 10              || ' '
 11              || TO_CHAR( MOD( FLOOR( s.last_call_et / 3600 ), 24 ), 'FM00' )
 12              || ':'
 13              || TO_CHAR( FLOOR( MOD( s.last_call_et, 3600 ) / 60 ), 'FM00' )
 14              || ':'
 15              || TO_CHAR( MOD( MOD( s.last_call_et, 3600 ), 60 ), 'FM00' )
 16             , 12
 17             )                         AS idle
 18            , s.machine                     AS computer
 19         FROM v$session s
 20            , v$process p
 21  --       , v$sesstat t
 22  --       , v$statname n
 23         WHERE  s.paddr = p.addr (+)
 24  --       AND s.sid = t.sid (+)
 25  --       AND t.statistic# = n.statistic#
 26  --       AND n.name = 'session uga memory'
 27            AND ( s.username LIKE 'MOD%'
 28           OR s.username LIKE 'MAIN_ADMIN%'
 29            )
 30         ORDER BY s.logon_time
 31  /

PROCESS LOGON                SID  SERIAL ACT SRV USER_NAME        IDLE          
------- -------------------- ---- ------ --- --- ---------------- ------------  
COMPUTER                                                                        
----------------------------------------------------------------                
10987   16 Oct 2003 10:10:49   19    252 INA NON MOD_APP_USER       0 22:14:55  
citora14.COMP.com                                                                
                                                                                
10987   16 Oct 2003 10:21:38   46   4144 INA NON MOD_APP_USER       0 15:12:44  
COMP\SYS10377                                                                    
                                                                                
10991   16 Oct 2003 10:37:39   10   1910 INA NON MOD_APP_USER       0 21:52:16  
COMP\SYS2707                                                                     
                                                                                
10985   16 Oct 2003 11:29:45   39   4209 INA NON MOD_APP_USER       0 14:41:57  
COMP\SYS10404                                                                    
                                                                                
10991   16 Oct 2003 11:58:40   40   5767 INA NON MOD_APP_USER       0 18:19:28  
COMP\SYS2668A                                                                    
                                                                                

SQL>     SELECT    TO_CHAR(sid, '999')                 AS sid
  2            , TO_CHAR(piece, '999')                 AS line
  3            , cur_prev                     AS c
  4            , TRANSLATE(sql_text, CHR(9) || CHR(10) || CHR(13), '   ')
  5                                   AS sql
  6         FROM (
  7      SELECT    s.username                     AS username
  8            , 'c'                         AS cur_prev
  9            , s.sid                         AS sid
 10            , q.piece                      AS piece
 11            , q.sql_text                     AS sql_text
 12         FROM v$session s
 13            , v$sqltext q
 14         WHERE  s.sql_hash_value = q.hash_value
 15            AND s.sql_address = q.address
 16      UNION
 17      SELECT    s.username                     AS username
 18            , 'p'                         AS cur_prev
 19            , s.sid                         AS sid
 20            , q.piece                      AS piece
 21            , q.sql_text                     AS sql_text
 22         FROM v$session s
 23            , v$sqltext x
 24            , v$sqltext q
 25         WHERE  s.sql_hash_value = x.hash_value (+)
 26            AND s.sql_address = x.address (+)
 27            AND x.address IS NULL
 28            AND s.prev_hash_value = q.hash_value
 29            AND s.prev_sql_addr = q.address
 30           ) t
 31         WHERE ( username LIKE 'MOD%'
 32           OR username LIKE 'MAIN_ADMIN%'
 33            )
 34         ORDER BY sid, cur_prev, piece
 35  /

SID  LINE C SQL                                                                 
---- ---- - ----------------------------------------------------------------    
  10    0 c SELECT * FROM "APPS"."COMP_AMG_ORG_V" ORDER BY "ORG_TYP    
  10    1 c E" ASC                                                              
  19    0 c update TABLE2 set TABLE2_STATUS_ID = :1, TABLE2  
  19    1 c _CRITICALITY_ID = :2, DUE_BY_DATE = :3, DUE_BY_MEET    
  19    2 c _ACTIVITY_ID = :4, STATE_SUBJECT_ID = :5, TABLE2_ACT    
  19    3 c ION_ID = :6, OPEN_MEET_KSAT_ID = :7, CLOSE_MEET_KSAT    
  19    4 c _ID = :8, OPEN_INSP_KSAT_ID = :9, CLOSE_INSP_KSAT_ID    
  19    5 c  = :10, MEET_ITEM_ID = :11, CAF_ID = :12, MSI_CLAUSE     
  19    6 c = :13, EQS_CLAUSE = :14, LEGACY_IND = :15, ITEM_NO = :16, DUE_BY    
  19    7 c _YEVR_TYPE_ID = :17, TABLE2_MEET_ID = :18, PLAN_    
  19    8 c ECCA_KSAT_ID = :19, PREVIOUS_TABLE2_ID = :20, ORIG    
  19    9 c INAL_TABLE2_ID = :21 where TABLE2_ID = :22          
  39    0 p SELECT rowid, "AGR"."CAF_AGR_IVER".* FROM "    
  39    1 p AGR"."CAF_AGR_IVER"  Where  CAF_ID = 1    
  39    2 p 12408                                                               

15 rows selected.

SQL> spool off

---------------------------- 

Tom Kyte
October 20, 2003 - 8:20 am UTC

it is probably your connection pool. nothing "strange" about that. thats just the last sql they executed.

Inactive sessions

A reader, October 20, 2003 - 9:20 am UTC

Tom,
Do these inactive session lead to blocked sessions?

>>it is probably your connection pool.
Should anything be modified on the connection pool setup?


Thank you

Tom Kyte
October 20, 2003 - 10:07 am UTC

not really -- it is doing what it is supposed to be doing -- pooling connections, having the connections "already there"

Inactive sessions

A reader, October 20, 2003 - 11:26 am UTC

Tom,
For how long after the SQLs have been executed will v$sqltext have these SQLs?
Is there anyway to prove that these inactive sessions with SQLs do not cause blocking. We are running into situations where we have blocked sessions once in a while, and the DBA says that these inactive sessions with associated SQLs lead to blocked sessions.

Thank you


Tom Kyte
October 20, 2003 - 11:30 am UTC

could be years and years.
could be days
could be minutes

it is not really "relevant".


I never said an inactive session would not block someone -- they certainly and surely can. That means someone did a transction and forgot to commit (aka: a bug in your code).

They can certainly hold locks. The SQL -- that is meaningless -- you want to look at v$lock and see what outstanding locks these inactive sessions may have.


Inactive sessions

A reader, October 20, 2003 - 12:17 pm UTC

Thank you

where are the comments in the code?

Joe, October 20, 2003 - 12:42 pm UTC

Tom,

The debug.f zip file that is posted on the debugf link contains sql with no comments for the package body or anything else. the code the user posted had comments about how to use the package, did the reader add all the comments, or have access to a version that contained them?




Tom Kyte
October 20, 2003 - 2:13 pm UTC

well, the comments are here, you can grab this version.

i honestly don't know where the verbose comments came from

To Joe:

A reader, October 20, 2003 - 1:51 pm UTC

Hi Joe
I *think* I got the debug.f from "Scripts" section of
</code> http://asktom.oracle.com/~tkyte/article2/index.html#Errors

I believe the latest version (published) is available
at: 

"Beginning Oracle Programming" book's source code
at apress
http://support.apress.com/books.asp?bID=186100690x&s=0&Go=Select+Book <code>

Not all comments are mine - I just added comments
for the new features I added to the debug.f.
Actually, the posting I had is an older version.
I emailed Tom a version with some enhancements
to it - he has been (understandably so) too caught up to
review it so far.



Inactive sessions

A reader, December 30, 2003 - 12:01 am UTC

Reg. the Inactive sessions in the above posting
>>That means someone did a transction and forgot to commit

>>They can certainly hold locks. The SQL -- that is meaningless -- you want to
>>look at v$lock and see what outstanding locks these inactive sessions may have.


The inactive session is running a package having a couple of select statements. Do we have to look at v$lock for select statements?
Will not closing a cursor/connection lead to an inactive sessions?

Thank you


Tom Kyte
December 30, 2003 - 10:04 am UTC

select statements do not take locks. (unless they are for update and then they are really update statements in disguise).

you want to look at the objects the session has locked.


an inactive session is just a session that is established and isnt currently running any sql

Same kind of problem

Sanjaya Balasuriya, January 06, 2004 - 4:47 am UTC

Hi Tom,

I also have experienced such behavior.
In one of our customer sites, it take a long time to make the connection to the database.Terribly a long time. 2,3 minutes.
But there after, the response for the applications is more or less OK.

What could be the possible reasons ?

Thanks in advance.


Tom Kyte
January 06, 2004 - 8:44 am UTC

funny -- none of threads in here have to do with "taking a long time to connect" (true, many refer to long connection times but in the context of "it was connected for 48+ hours", not in the context of "it took 48+ hours to connect" )


Taking a long time to connect is many times due to improper DNS setup. Use tnsping, can you tnsping the listener fast or slow. If you cannot tnsping it fast, it indicates a network setup issue.

So, what is your tnsping time.

Also, whats in your sqlnet.ora on the clients. whats your version. whats your os, etc etc etc.

Not related with memory ?

Sanjaya Balasuriya, January 07, 2004 - 11:51 pm UTC

Hi Tom,

Thanks for the guidance
And isn't this problem related with insufficient memory allocated for the database ?
Since the memory from shared pool is used to establish a session (am I incorrect ?), can't be this happen due to not enough memory in the shared pool ?
I think so because this problem is occurred during the peak hours ?

Thanks in advance.


Tom Kyte
January 08, 2004 - 12:50 pm UTC

no, you'd get an "i'm so sorry, we are out of memory" error.


are you using shared server or dedicated server.

Additional information

Sanjaya Balasuriya, January 10, 2004 - 9:48 am UTC

Hi Tom,

Thanks for help.

And I'm using dedicated server.



Tom Kyte
January 10, 2004 - 10:58 am UTC

nope, not an SGA issue and not a shared server problem (could have been too few shared servers)

dedicated server
slow down connecting during peak
sounds like could be overloaded machine.

Thanks a lot

Sanjaya Balasuriya, January 10, 2004 - 11:49 pm UTC

Thanks Tom for help.

I'll check what I can do to reduce the load of the server.
The CPUs of the server are always over 90% utilized.

Thanks for the guidance.


url based debugging question

A reader, January 16, 2004 - 4:31 pm UTC

What happens when parameters are not passed through the
URL but are passed through POST? Any thoughts? How
do you turn on the debugging in this case?
thanx!

Tom Kyte
January 17, 2004 - 1:14 am UTC

post and get are the same in mod_plsql as far as we are concerned. what differences do you see? to me, well, in the mod_plsql routine I cannot really tell the difference between the two.

thanx tom!

A reader, January 17, 2004 - 1:05 pm UTC

I have not tried it out - we are not using mod_plsql
though - j2ee based architecture (jsp/servlet) -
I will post my findings once I have done some experiments...


a question

A reader, January 23, 2004 - 10:23 am UTC

Tom
Do you think it is a good idea to enable sql trace also
from the URL (based on client id and the new dbms_monitor/
end to end tracing facility in 10g.) This would enable us to generate trace files for activities of one end user for rendering a particular url. Combined with our instrumentation this could be very useful....What do you think?

Tom Kyte
January 23, 2004 - 6:29 pm UTC

i do it on every thing I build.

Killing the inactive Sessions

A reader, April 29, 2004 - 11:44 am UTC

Well i have set the session idle time to 5 minutes. The user is disconnected but the connection stays there. We are using JAVA programs for establishing the connection and recording the transaction also we use ASP for our webpages. At times Logons cumulative shows some BIG number and the current cursors cumulative is equally huge. The open cursors parameter has been set to 500. But i know that this parameter has no overhead.
My question is what should we do to make sure that the User is also disconnected after being idle for 5 mins. or more, without me having to kill that session manually. The connection is terminated completely. And will the resources held by them be released back? Database version is Oracle 9i Release 2. And we are using Shared Server Architecture. Should something to be changed in Profile or a peice of code be added in JAVA.
Thanks.


Tom Kyte
April 29, 2004 - 11:54 am UTC

the connection will stay there, killed -- that is totally by design.

else, when the connection is eventually used, the user would get "ora-3113 eof on comm channel" and calls to support would abound.

the resources are freed -- especially if you are using shared server, since you do not have a dedicated server.

Help Required........

A reader, June 07, 2004 - 7:20 pm UTC

Hi Tom,
I have the following problem.
We have Java programs running on the Server where Oracle 9iR2 is installed on Windows 2000 Advanced Server.
The Java procedures are using Connection Pooling and Shared Server Architecture is activated.
The sessions opened by the Java Programs are not being closed properly even though I have set idle_time to 5 minutes. Resource_Limit is set to False and SQLNET.EXPIRE_TIME is set to 1.
I had to painstakingly kill 61 inactive sessions. :(
I had activated Resource_Limit to True in the past but then set it to False again due to the fear that the Java Programs do not get disconnected if they stay inactive for more than 5 minutes and bear the brunt of the clients.
Please help us in resolving this grave problem.
Thanks a lot as always. :)


Tom Kyte
June 07, 2004 - 7:39 pm UTC

"The Java procedures are using Connection Pooling and Shared Server Architecture
is activated."

a buffer for a buffer, a cache of a cache.

connection pooling achieves what shared server was designed for. you don't need both.


you should use dedicated server.
you should let the sessions live for as long as the connection pool wants them to.

if you time out a connection pool connection -- you're in for a whole world of pain and confusion. The connection pool is where you would control this (if anywhere, the GOAL of a connection pool is to *keep the sessions open*)



dbms_session with connection pools

dxl, July 06, 2004 - 10:52 am UTC

We have a package which uses dbms_session to set the context variable for dynamic sql

queries like:



IF ( P_Org_String IS NOT NULL ) THEN

V_Org_String := P_Org_String;
FOR i IN 1 .. 99999 LOOP
l_n := INSTR( V_Org_String, ',' );
EXIT WHEN (NVL(l_n, 0) = 0);
DBMS_SESSION.SET_CONTEXT( 'MY_CTX', 'in_list_' || i, LTRIM(RTRIM(SUBSTR( V_Org_String, 1, l_n-1)) ));
V_Org_String := SUBSTR( V_Org_String, l_n+1 );

END LOOP;


l_query := l_query ||' AND o.Org_ID IN ( SELECT TO_NUMBER(Value)
FROM Session_Context
WHERE Namespace = ''MY_CTX''
AND Attribute LIKE ''IN\_LIST\_%'' escape ''\'' )';


END IF;


We call the package from a jdbc client using connection pools.
Now this package runs fine from sqlplus and also works the majority of the time from the application. However every now and again we get the following errors reported from users running the package from the jdbc client:

java.sql.SQLException: ORA-01031: insufficient privileges
ORA-06512: at "SYS.DBMS_SESSION", line 62
ORA-06512: at "OPT1.PKG_SBE515", line 1157
ORA-06512: at line 1

line 1157 is the line which sets the context:

DBMS_SESSION.SET_CONTEXT( 'MY_CTX', 'in_list_' || i, LTRIM(RTRIM(SUBSTR( V_Org_String, 1, l_n-1)) ));



When i run the package from sqlplus it is fine.
What could be causing this?
I thought this type of error was due to a user not having permission to access the session variables ?

Could it be that the session variables are lost between connection pools or that the user that set them is now using a different connection pool hence different session variable??

i don't use dbms_session.reset_package_state at all, so should i be??

Please help with this.

Thanks



Tom Kyte
July 06, 2004 - 11:27 am UTC

that should only happen if the context was not created with "using pkg_sbe515"

if it happens intermittently -- it would be "a bug". You'll need to contact support and they can help you set an event to get further trace information for this.

It should either always fail, or not ever fail with that error.

Re: dbms_session with connection pools

A reader, July 06, 2004 - 11:58 am UTC

To dxl:
Is it possible that some of your connection pool
connections dont have appropriate privilege?
I am aware that typically we have the same user privileges
for all connections in a pool...

Tom Kyte
July 06, 2004 - 2:09 pm UTC

the package is what needs the "priv".

it should either always work, or never work.


if the connection can execute the package (and this one did), it should either always get the 1031 or never get it in this case.

thanks

dxl, July 06, 2004 - 12:22 pm UTC

Ok this may well be a bug then because i can definitely use the package from sqlplus but when using the jdbc client it failed.
I then recreated the context and the jdbc client calling the package is now working fine. Guess i'll have to keep an eye on this.

-- To the reader: yes we are using connection pools which all use the same database login hence same privileges, it is even the same user that i ran the package from in sqlplus.


But this has raised another concern of mine about connection pools and setting session variables or namespaces.

referring to another question posted:

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1486405001956, <code>

Your first reply is :

"...
1) jdbc connection pooling is typically done by having a common username log
into the database -- the software then maintains a pool of open connections all
under the same user account. when your program needs a connect, one of the
common connections is returned to you. when you are done, it is given back to
the pool for the next guy. In the database you all appear to be the same user
in the same session.
..."

This implies that if you set a session variable from a package using dbms_session.set_context it will be available to another user who grabs this same connection from the pool doesn't it?? So the package that this new user uses is already polluted with session variables from the previous user running the same package??

Have i got this wrong? if i'm right how do i get around this problem?

Tom Kyte
July 06, 2004 - 2:10 pm UTC

yes, it would be "polluted"

you deal with it the same exact way you deal with ANY global variable in an application -- you initialize them before refering to them.

To dxl:

A reader, July 06, 2004 - 12:30 pm UTC

Before returning the connection, I believe
you should execute the following to reset the package
states and values created in that session.

DBMS_SESSION.reset_package

Tom Kyte
July 06, 2004 - 2:15 pm UTC

ops$tkyte@ORA9IR2> select * from session_context;
 
NAMESPACE                      ATTRIBUTE
------------------------------ ------------------------------
VALUE
-------------------------------------------------------------------------------
MY_CTX                         EMP.ENAME
SMITH
 
MY_CTX                         EMPLOYEE_SOUNDEX_INDICATE_ON
Y
 
 
ops$tkyte@ORA9IR2> exec dbms_session.reset_package;
 
PL/SQL procedure successfully completed.
 
ops$tkyte@ORA9IR2> select * from session_context;
 
NAMESPACE                      ATTRIBUTE
------------------------------ ------------------------------
VALUE
-------------------------------------------------------------------------------
MY_CTX                         EMP.ENAME
SMITH
 
MY_CTX                         EMPLOYEE_SOUNDEX_INDICATE_ON
Y
 
 
ops$tkyte@ORA9IR2>


that gets the package state.
 

thanx!

A reader, July 06, 2004 - 2:19 pm UTC

I did not read the question by "dxl" properly:)

how?

dxl, July 07, 2004 - 4:45 am UTC

So how best should i initialise the session_Context values before referencing them?

How about something like:

For rec_Cur IN (SELECT *
FROM Session_Context) LOOP

i := i + 1;

DBMS_SESSION.SET_CONTEXT( 'MY_CTX', 'in_list_' || i, null);

END LOOP;


I tried this, but when i ran it on our test instance i got:

09:18:41 OPT1@OP5>exec PKG_SBE515.P_Get_SBETables ( '1/Sep/2003', '142,213', 'Y', :x);
BEGIN PKG_SBE515.P_Get_SBETables ( '1/Sep/2003', '142,213', 'Y', :x); END;

*
ERROR at line 1:
ORA-03113: end-of-file on communication channel



How would you "initialise" the session values??

Tom Kyte
July 07, 2004 - 8:32 am UTC

dbms_session.clear_context

although, for a 3113 like that -- please contact support if you have the reproducible test case. that should be OK (what you are doing)

not available

dxl, July 07, 2004 - 9:22 am UTC

It seems that the dbms_session package does not have that procedure:

13:53:09 OPT1@OP5>@C:\oph\Procedures\sbe_515\P_Load_SBE_Data.sql

Warning: Package Body created with compilation errors.

Elapsed: 00:00:02.02
13:53:12 OPT1@OP5>show err
Errors for PACKAGE BODY PKG_SBE515:

LINE/COL ERROR
-------- ----------------------------------------------------------------
1272/1 PL/SQL: Statement ignored
1272/14 PLS-00302: component 'CLEAR_CONTEXT' must be declared
13:53:14 OPT1@OP5>


This was confirmed by looking at the package spec in the
$ORACLE_HOME/rdbms/admin/dbmsutil.sql

file. However there is also a procedure called:

dbms_session.modify_package_state

which looks like it may do the right job, but whilst it exists in the

$ORACLE_HOME/rdbms/admin/dbmsutil.sql

file spec i can't see it when i desc the package:

13:53:14 OPT1@OP5>desc dbms_session
PROCEDURE CLOSE_DATABASE_LINK
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
DBLINK VARCHAR2 IN
PROCEDURE FREE_UNUSED_USER_MEMORY
FUNCTION IS_ROLE_ENABLED RETURNS BOOLEAN
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
ROLENAME VARCHAR2 IN
FUNCTION IS_SESSION_ALIVE RETURNS BOOLEAN
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
UNIQUEID VARCHAR2 IN
PROCEDURE LIST_CONTEXT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
LIST TABLE OF RECORD OUT
LSIZE NUMBER OUT
PROCEDURE RESET_PACKAGE
PROCEDURE SET_CLOSE_CACHED_OPEN_CURSORS
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
CLOSE_CURSORS BOOLEAN IN
PROCEDURE SET_CONTEXT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
NAMESPACE VARCHAR2 IN
ATTRIBUTE VARCHAR2 IN
VALUE VARCHAR2 IN
PROCEDURE SET_NLS
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
PARAM VARCHAR2 IN
VALUE VARCHAR2 IN
PROCEDURE SET_ROLE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
ROLE_CMD VARCHAR2 IN
PROCEDURE SET_SQL_TRACE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
SQL_TRACE BOOLEAN IN
PROCEDURE SWITCH_CURRENT_CONSUMER_GROUP
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
NEW_CONSUMER_GROUP VARCHAR2 IN
OLD_CONSUMER_GROUP VARCHAR2 OUT
INITIAL_GROUP_ON_ERROR BOOLEAN IN
FUNCTION UNIQUE_SESSION_ID RETURNS VARCHAR2

13:56:42 OPT1@OP5>

I know the source is wrapped but why is this package different from its spec? We originally installed 8.1.7 on hpux 11i 64bit and then upgraded to 8.1.7.4, but i can't find any other file with the dbms_Session package spec in it apart from the one mentioned above?
Do you have a spec with clear_context procedure in it??

Tom Kyte
July 07, 2004 - 9:45 am UTC

I was looking at 9i.

in 8i, you used set_context to reset the value. the 3113 should not happen, please contact support for assistance with that


modify_package_state is not anything you want or need, you are not touching a plsql package state here, you are dealing with an application context, a totally different thing.

Session info

RD, September 09, 2004 - 10:04 pm UTC

Hi Tom,

We are using an Oracle8i database with Vantive ( a peoplesoft product). The application takes around twenty
connections and then pools them to oracle.
Last evening when someone reported that suddenly the
system is running slow I looked into the Toad sessions
viewer and got this :-


SID USER# USERNAME
-------- ---------- ----------
37 15556 VANTIVE
38 14 FS7SYSDB
39 14 FS7SYSDB
40 14 FS7SYSDB
41 8200 FS7SYSDB
42 23772 SYSTEM
43 21465 SYSTEM
44 15 FS7SYSDB
46 42063 FS7SYSDB
47 9931 FS7SYSDB
48 7765 VANTIVE and more.......

Here almost all the users are 'FS7SYSDB' with distinct sid's
and serial#. What really gets me is how will I identify who the user is (so I can talk to them regarding what they were running at that instant(sql)), there are hundreds of 'FS7SYSDB'. PLEASE help .... how can I pinpoint who the user was??/ all users sit mostly in our helpdesk/support
hall.

What else can I do in similar scenerios and how?

Thanks yet yet again as always,
Regards,
RD.

Tom Kyte
September 10, 2004 - 7:55 am UTC

the user was FS7SYSDB.....

you can look at other columns in v$session  

select username, osuser, process, machine, terminal, program, logon_time, status from v$session
where username is not null
 
USERNAME                       OSUSER                         PROCESS
------------------------------ ------------------------------ ------------
MACHINE
----------------------------------------------------------------
TERMINAL                       PROGRAM
------------------------------ ------------------------------------------------
LOGON_TIM STATUS
--------- --------
OPS$TKYTE                      tkyte                          10515
xtkyte-pc.us.oracle.com
pts/0                          sqlplus@xtkyte-pc.us.oracle.com (TNS V1-V3)
10-SEP-04 ACTIVE
 


shows that the database user OPS$TKYTE was logged into his operating system as tkyte, the process ID on that machine was 10515 -- the host he was on was xtkyte-pc.us.oracle.com, he had terminal pts/0 and appears to have been running sqlplus... 

More

RD, September 12, 2004 - 8:34 pm UTC

Hi Tom,
I used the sql you suggested and the result is not helping me identify who the user is still or am I looking for the wrong thing here..

select username, osuser, process, machine, terminal, program, logon_time, status
from v$session
where username is not null;

FS7SYSDB SYSTEM 2288:2284 WANGNZ\AKAS1 AKAS1 PSBRKHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2264:2272 WANGNZ\AKAS1 AKAS1 PSBRKHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2824:2664 WANGNZ\AKAS1 AKAS1 PSPUBDSP.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2500:2820 WANGNZ\AKAS1 AKAS1 PSPUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2832:2496 WANGNZ\AKAS1 AKAS1 PSPUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2844:2836 WANGNZ\AKAS1 AKAS1 PSPUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 676:2848 WANGNZ\AKAS1 AKAS1 PSSUBDSP.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2860:2856 WANGNZ\AKAS1 AKAS1 PSSUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2868:2864 WANGNZ\AKAS1 AKAS1 PSSUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB SYSTEM 2880:2872 WANGNZ\AKAS1 AKAS1 PSSUBHND.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 480:2820 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 2668:2772 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 2648:2664 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 3148:3136 WANGNZ\AKDB10 AKDB10 PSDSTSRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 2624:2656 WANGNZ\AKDB10 AKDB10 PSPRCSRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 3176:1880 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 3196:3180 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 3216:3200 WANGNZ\AKDB10 AKDB10 PSAESRV.exe 11-SEP-04 INACTIVE
FS7SYSDB Admin_PSoft 3236:3220 WANGNZ\AKDB10 AKDB10 PSPRCSRV.exe 11-SEP-04 INACTIVE


This is like wanting to know who the user is and seeing that everyone connected is called TKYTE.

Couold you please also advice as to what steps to take in the given scenerio when suddenly one gets a call that the database has suddenly become very slow?

THANKS Tom,
RD.


Tom Kyte
September 13, 2004 - 7:31 am UTC

you'll have to open a call to your people soft technical contacts and say "sooo, given that you use the same account, how do I figure out whats up?"

there isn't anything we can do here -- you are using peoplesoft, everything is coming in as a single user from their middle tier. We in the database have NO CLUE who is "there"

I would compare what the database is doing now as oppposed to what it typically did -- you do have those statspacks and load details from when the system was running "good" right?

Pravesh Karthik, September 15, 2004 - 11:55 am UTC

Tom,

A general, but highly technical answer 'requested' from your side. If a load runs slower, and a developer ask me, why its very slowly running.

where do i need to start and what all i need to check.

I do check for any waits/locks.. otherwise?

Thanks a lot
Pravesh Karthik

Tom Kyte
September 15, 2004 - 12:00 pm UTC

10046 level 12 trace and tkprof. analyze results.

Inactive Sessions causing database to Hang

Vivek Sharma, January 05, 2006 - 9:42 am UTC

Hi Tom,

Greetings !

I have one of the my application which makes connection to the database from a WEBSPHERE using Connection Pooling.

At some point of the time, the connection to the database become INACTIVE and when these connections pile up to 200 or so, the database hangs. Only after killing these connections, the database starts functioning fine.

The Database is a using purely Dedicated Server Connection. I could see the queries which are not optimized and feel that when these queries are executed from the application, the sessions become INACTIVE after some point of time. Though, I am not ruling out any possibility of problem at Connection Pooling level (WEBSPHERE), I feel that Database performance also matters. The parameters optimizer_index_cost_adj is 1 and caching is set to 95 which is forcing Index usage via NESTED LOOP and thus causing the bottleneck. Would like to know, whether can an inefficient application queries also cause the INACTIVE Session problem ?

Regards
Vivek


Tom Kyte
January 05, 2006 - 11:02 am UTC

The problem is likely in the connection pool/middle tier software.

Oracle responds to "create me a session" and "I'm done with this session". Websphere is giving us the "create me a session" - but apparently is not for whatever reason effectively reusing them (perhaps you have a buggy application that grabs a connection and forgets to return it to the pool???)



A reader, January 05, 2006 - 10:50 pm UTC

I have read this problem on lot of threads in google groups as well.

A reader, November 14, 2006 - 8:06 pm UTC

We have a web application that uses Oracle 9i database. The application runs on sun one web server. Normally the number of inactive sessions in the database is around 20. Yesterday, there were 150 of them and the application was slow. When I checked the number of sessions/threads the web server was handling it was 400. 400 is the maximum limit. On earlier occassions, when the application was slow, the threads never went to the maximun limit. How are these two dependent? Does the web server issue more threads due to database slowness? I am trying to find the problem here? Is it due to the inactive sessions? Should we schedule something and terminate them automatically?


Tom Kyte
November 15, 2006 - 6:54 am UTC

ask your webserver people?



about RUNTIME_MEM

rain, January 29, 2007 - 1:36 am UTC

Hi, Tom
Our WEB AP is JAVA base . use normal dedicate server mode .
when I monitor the session (v$session join v$sql) , there are some result like:

OS_ADD LOGON_TIME DBUSER SESSION_ID SQL_ADDR RUNTIME_MEM EXES LOADS
315E40EC 01-29 13:02:34 BUSIN 15,36410 2CE08344
315DE32C 01-29 10:14:05 BUSIN 63,18354 2E3FBE84 0 0 1

1. In first row ,the runtime_mem is null? in second row is 0. what different between null and 0 ?
I suspect that java had't closed and released the connection resource completed,
because it always produced huge runtime_mem=null or 0 sessions and they are keep long time.
2. in each runtime_mem=0, all of their exes=0 and loads=1 why ?

thank
regard