Oracle SERIAL# changing for the same SID - oracle

I'm using Oracle19c with a thin client and I'd like to set traces on the 5 application connections with
EXEC DBMS_SYSTEM.set_sql_trace_in_session(sid, serial#, true ) so I created a stored procedure.
When I select the SID and SERIAL# with:
select sid, serial#, osuser, machine, program, module, username
from v$session WHERE username IS NOT NULL ORDER BY username ASC;
I noticed that the SERIAL# keeps changing every minute or so, but I don't have any connection timeout set for the user: it's using the DEFAULT profile and LIMIT='UNLIMITED'.
Is there a way to "extend the life" of those connections?

A new serial# is a new session. This probably means the application doing the connecting is diconnecting/reconnecting, possibly by design at regular intervals, or possibly by error and its dropping the connection and recovering by commencing a new one.
But you'll need to look inside the app to see that, not the database.
If you want to trace such an app, you could create a LOGON trigger to turn on trace as soon as they connect, rather than trying to catch it with a query to v$session, eg
create or replace
trigger TRACE_ALL_LOGINS
after logon on MY_DB_ACCOUNT.schema
begin
execute immediate 'alter session set tracefile_identifier = BLAH';
execute immediate 'alter session set events = ''10046 trace name context forever, level 12''';
exception
when others then null;
end;
/
I keep the when-others-then-null in this special case to ensure that if the trigger fails for some reason, we don't block the ability to connect at all.

Related

Access control monitoring in Oracle

Is there any table or log that shows the connection attempts to an oracle database (I don't mean the active sessions, but attempts, even though they've failed or been denied)?
The information I need is the IP from which has been done the attempt, the user used, the executable used (sqlplus, toad, sqldeveloper, java ...), etc.
I guess you need Oracle Listener logging.
You can use a DATABASE TRIGGER, see CREATE TRIGGER
Example:
CREATE OR REPLACE TRIGGER MY_TRIGGER
AFTER LOGON ON DATABASE
DECLARE
BEGIN
INSERT INTO LOG_TABLE
SELECT
USERNAME, OSUSER, MACHINE, PROGRAM, --> columns in V$SESSION
ora_client_ip_address, ora_login_user, ora_sysevent --> Event Attributes from Trigger
FROM V$SESSION
WHERE SID = SYS_CONTEXT('USERENV', 'SID')
COMMIT;
END;
/
Here you see a list of all System-Defined Event Attributes: Coding Triggers
However, as stated this is a AFTER LOGON trigger, so failed attempts due to wrong password are not covered!

Oracle kill inactive sessions stored procedure

I would like to write kill_inactive sessions stored procedure for Oracle.
something like
create or replace procedure kill_inactive_sessions as
begin
for rec in (select sid, serial# from sys.v_$session where status = 'INACTIVE')
loop
execute immediate 'alter system kill session '''|| rec.sid || ',' || rec.serial# || ''' IMMEDIATE';
end loop;
end kill_inactive_sessions;
Previous doesn't work (table or view does not exists).
But next select is working perfectly for the same user:
select sid, serial# from sys.v_$session where status = 'INACTIVE';
What I'm missing?
The ORA-00942: table or view does not exist error almost certainly indicates that your access to the v$session view is via a role rather than a direct grant.
If you want to write a definer's rights stored procedure, the owner of the procedure must have the necessary privileges granted directly to the user, not via a role (and remember that DBA is just another role). Most likely, if you disabled roles in your session, the SELECT statement outside of the procedure would not work. In SQL*Plus, for example
SQL> set role none;
SQL> select sid, serial# from sys.v_$session where status = 'INACTIVE';
will likely throw the same ORA-00942 error. Assuming it does, you need to grant the user that owns the stored procedure privileges directly. For example
GRANT SELECT ANY DICTIONARY
TO user_that_owns_the_procedure;
The same thing will also apply to the ALTER SYSTEM command that you are building and running. The owner of the stored procedure will need to have privileges to run that command via a direct grant not via a role.
All that said, a procedure that kills all inactive sessions is highly problematic. The vast majority of sessions are going to be inactive the vast majority of the time. That doesn't mean that they should be killed. Even if you're cleaning up after an application server crash, you really ought to be applying some additional predicates (for example, looking for sessions from a particular machine that are logged in as a particular user that were established before the application server crashed). Long-term, though, I'd suggest enabling dead connection detection so that the database can automatically take care of closing sessions when the client process dies unexpectedly.

In oracle, can I associate a default Schema with my USER ID where SCHEMA <> USERID?

I would like to connect to an Oracle database with UserId "MY_SCHEMA" and then be able to perform queries where the table name was not qualified with the schema name:
SELECT * FROM TABLE1
When executing SQL, I would like my unqualified queries to go against a different schema other than my own. In other words, I would like this to be equivalent to
SELECT * FROM SCHEMA_OTHER.TABLE1
instead of
SELECT * FROM MY_SCHEMA.TABLE1
I know it seems a little weird and so I expect that this is not possible.
I do not have any sort of admin rights to the database to see if I can associate a default schema with a login.
After you login, you can run the following:
ALTER SESSION SET CURRENT_SCHEMA=schema_other;
If you really want this to happen automatically, you can create a system trigger for the logon action that looks for your username and uses execute immediate to run the alter session command:
CREATE OR REPLACE TRIGGER my_schema_logon
AFTER LOGON
ON DATABASE
BEGIN
IF SYS_CONTEXT ('USERENV', 'CURRENT_USER') = 'MY_SCHEMA' THEN
EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA=schema_other';
END IF;
END my_schema_logon;
/

Oracle: idle_time appears to be ignored

In my understanding, creating a profile with the idle_time set to a certain value (in minutes) and creating a user with this profile should force the SNIPED status for that user's session in case he is idle for longer than idle_time. When the user tries to execute a query after this has happened, he receives a message that he must connect again.
First question: Is that right? If so, read on:
I'm running a test script as follows in sqlplus (without the placeholders obviously):
connect system/<password>#<tns>
CREATE PROFILE test_profile LIMIT idle_time 1;
CREATE USER test_user PROFILE test_profile IDENTIFIED BY test_user;
GRANT CREATE SESSION TO test_user;
GRANT ALTER SESSION TO test_user;
GRANT SELECT ON <schema>.<table> TO test_user;
disconnect;
connect test_user/test_user#<tns>
SELECT * FROM <schema>.<table>;
Everything works up to this point; the sqlplus window is still open. Now I open an additional sqplus window and connect using the system account, running the following query after doing other stuff for a while:
SELECT username, status, seconds_in_wait FROM v$session WHERE username = 'test_user';
I get something like:
USERNAME STATUS SECONDS_IN_WAIT
--------- -------- ---------------
TEST_USER INACTIVE 1166
Why has the status not been set to SNIPED?
Obviously, If I run another query from the test_user's sqlplus window, I do not get a message asking me to reconnect.
You need to set the database's RESOURCE_LIMIT parameter to TRUE in order for resource limits in profiles to take effect. Assuming you use a spfile (otherwise omit the scope = BOTH part)
ALTER SYSTEM SET resource_limit = TRUE scope = BOTH
Once you do that, PMON should start sniping the sessions that have exceeded your IDLE_TIME when it wakes up every few minutes.

Dropping a connected user from an Oracle 10g database schema

Is there a better way to forcefully disconnect all users from an Oracle 10g database schema than restarting the Oracle database services?
We have several developers using SQL Developer connecting to the same schema on a single Oracle 10g server. The problem is that when we want to drop the schema to rebuild it, inevitably someone is still connected and we cannot drop the database schema or the user while someone is still connected.
By the same token, we do not want to drop all connections to other schemas because other people may still be connected and testing with those schemas.
Anyone know of a quick way to resolve this?
To find the sessions, as a DBA use
select sid,serial# from v$session where username = '<your_schema>'
If you want to be sure only to get the sessions that use SQL Developer, you can add and program = 'SQL Developer'. If you only want to kill sessions belonging to a specific developer, you can add a restriction on os_user
Then kill them with
alter system kill session '<sid>,<serial#>'
(e.g. alter system kill session '39,1232')
A query that produces ready-built kill-statements could be
select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v$session where username = '<your_schema>'
This will return one kill statement per session for that user - something like:
alter system kill session '375,64855';
alter system kill session '346,53146';
Find existing sessions to DB using this query:
SELECT s.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program
FROM gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
WHERE s.type != 'BACKGROUND';
you'll see something like below.
Then, run below query with values extracted from above results.
ALTER SYSTEM KILL SESSION '<put above s.sid here>,<put above s.serial# here>';
Ex:
ALTER SYSTEM KILL SESSION '93,943';
my proposal is this simple anonymous block:
DECLARE
lc_username VARCHAR2 (32) := 'user-name-to-kill-here';
BEGIN
FOR ln_cur IN (SELECT sid, serial# FROM v$session WHERE username = lc_username)
LOOP
EXECUTE IMMEDIATE ('ALTER SYSTEM KILL SESSION ''' || ln_cur.sid || ',' || ln_cur.serial# || ''' IMMEDIATE');
END LOOP;
END;
/
Make sure that you alter the system and enable restricted session before you kill them or they will quickly log back into the database before you get your work completed.
Just my two cents : the best way (but probably not the quickest in the short term) would probably be for each developer to work on his own database instance (see rule #1 for database work).
Installing Oracle on a developer station has become a no brainer since Oracle Database 10g Express Edition.
Have you tried ALTER SYSTEM KILL SESSION? Get the SID and SERIAL# from V$SESSION for each session in the given schema, then do
ALTER SCHEMA KILL SESSION sid,serial#;
just use SQL :
disconnect;
conn tiger/scott as sysdba;

Resources