Skip to main content

Oracle Database Check blocking sessions


Check blocking sessions

Let's create a scenario

/*
Create a blocking lock
To begin, create a situation where one user is actively blocking another. Open two sessions. Issue the following commands in Session 1 to build the test table:
*/
SQL> create table tstlock (foo varchar2(1), bar varchar2(1));

--Table created.
SQL> insert into tstlock values (1,'a');

--1 row created.
SQL> insert into tstlock values (2, 'b');

--1 row created.
SQL> select * from tstlock ;
FOO BAR
--- ---
1   a
2   b
--2 rows selected.
SQL> commit ;
--Commit complete.
--Now grab a lock on the whole table, still in Session 1:
SQL> select * from tstlock for update ;
--And in Session 2, try to update a row:
SQL> update tstlock set bar= 2  'a' where bar='a' ;
--This statement will hang, blocked by the lock that Session 1 is holding on the entire table.


/*Identify the blocking session
Oracle provides a view, DBA_BLOCKERS, which lists the SIDs of all blocking sessions. But this view is often, in my experience, a good bit slower than
simply querying V$LOCK, and it doesn't offer any information beyond the SIDs of any sessions that are blocking other sessions.
The V$LOCK view is faster to query, makes it easy to identify the blocking session, and has a lot more information.
*/
SQL> select * from v$lock ;

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
AF9E2C4C AF9E2C60        479 TX     131078      16739          0          6        685          0
ADDF7EC8 ADDF7EE0        422 TM      88519          0          3          0        697          0
ADDF7F74 ADDF7F8C        479 TM      88519          0          3          0        685          0
ADEBEA20 ADEBEB3C        422 TX     131078      16739          6          0        697          1


/*
Note the BLOCK column. If a session holds a lock that's blocking another session, BLOCK=1. Further, you can tell which session is being blocked
by comparing the values in ID1 and ID2. The blocked session will have the same values in ID1 and ID2 as the blocking session, and,
since it is requesting a lock it's unable to get, it will have REQUEST > 0
*/

--In the query above, we can see that SID 422 is blocking SID 479. SID 422 corresponds to Session 1 in our example, and SID 479 is our blocked Session 2.

--To avoid having to stare at the table and cross-compare ID1's and ID2's, put this in a query:

SQL> select l1.sid, ' IS BLOCKING ', l2.sid
  from v$lock l1, v$lock l2
  where l1.block =1 and l2.request > 0
  and l1.id1=l2.id1
  and l1.id2=l2.id2

SQL> /
       SID 'ISBLOCKING'         SID
---------- ------------- ----------
       422  IS BLOCKING         479
--1 row selected.

--Even better, if we throw a little v$session into the mix, the results are highly readable:

SQL> select s1.username || '@' || s1.machine
  || ' ( SID=' || s1.sid || ' )  is blocking '
  || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status
  from v$lock l1, v$session s1, v$lock l2, v$session s2
  where s1.sid=l1.sid and s2.sid=l2.sid
  and l1.BLOCK=1 and l2.request > 0
  and l1.id1 = l2.id1
  and l2.id2 = l2.id2 ;


BLOCKING_STATUS
----------------------------------------------------------------------------------------------------
BULKLOAD@yttrium ( SID=422 )  is blocking BULKLOAD@yttrium ( SID=479 )
--1 row selected

-- Check what queries are running in these SID

SELECT a.sid,a.serial#,b.sql_text FROM
    v$session a,v$sqlarea b
WHERE a.sql_address = b.address;

--specific SID

SELECT a.sid,a.serial#,b.sql_text
FROM
    v$session a,v$sqlarea b
WHERE a.sql_address = b.address   AND   a.sid = '42';

--Check blocking sessions using v$session

SELECT
   s.blocking_session,
   s.sid,
   s.serial#,
   s.seconds_in_wait
FROM
   v$session s
WHERE
   blocking_session IS NOT NULL;

   
-- Identifying blocked objects
SELECT sid, id1 FROM v$lock WHERE TYPE='TM';
SELECT object_name FROM dba_objects WHERE object_id=79159;

-- get deailed information bt instance

SELECT 'Instance '||s1.INST_ID||' '|| s1.username || '@' || s1.machine
   || ' ( SID=' || s1.sid || ','|| s1.serial#||s1.status||  '  )  is blocking '
   || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' ||s2.sql_id
    FROM gv$lock l1, gv$session s1, gv$lock l2, gv$session s2
   WHERE s1.sid=l1.sid AND
    s1.inst_id=l1.inst_id AND
    s2.sid=l2.sid AND
    s2.inst_id=l2.inst_id AND
    l1.BLOCK=1 AND
   l2.request > 0 AND
   l1.id1 = l2.id1 AND
   l2.id2 = l2.id2 ;

--check sql for the SID
select sql_id from v$session where sid=42;
select sql_fulltext from v$sql where sql_id ='01zffbm7nxg6c';


/*Killing Oracle Sessions
Be very careful when identifying the session to be killed. If you kill a session belonging to a background process you will cause an instance crash.
There are a number of ways to kill blocking sessions both from Oracle sql prompt and externally.
Identify the Session to be Killed
ALTER SYSTEM KILL SESSION
ALTER SYSTEM DISCONNECT SESSION
The Windows Approach
The UNIX Approach
*/

-- Find the serial for blocking session SID
select SERIAL# from v$session where SID=39; -- result 130


--Final step to kill the blocking session alter system kill session ‘SID,SERIAL#’;

SQL> alter system kill session ‘39,130’;

--System altered.

SQL> ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
--This does not affect the work performed by the command, but it returns control back to the current session immediately, rather than waiting for confirmation of the kill.
--In a RAC environment, you optionally specify the INST_ID, shown when querying the GV$SESSION view. This allows you to kill a session on different RAC node.
SQL> ALTER SYSTEM KILL SESSION 'sid,serial#,@inst_id';
SQL> ALTER SYSTEM DISCONNECT SESSION 'SID,SERIAL#' IMMEDIATE;
--The DISCONNECT SESSION command kills the dedicated server process, which is equivalent to killing the server process from the operating system

kill -9 spid

Comments

Popular posts from this blog

Oracle Database How much redo generated per hour

Track the Amount of Redo Generated per Hour / Day  Amount of Redo Generated per Hour SELECT  Start_Date,   Start_Time,   Num_Logs, Round(Num_Logs * (Vl.Bytes / (1024 * 1024)),2) AS Mbytes, Vdb.NAME AS Dbname FROM (SELECT To_Char(Vlh.First_Time, 'YYYY-MM-DD') AS Start_Date, To_Char(Vlh.First_Time, 'HH24') || ':00' AS Start_Time, COUNT(Vlh.Thread#) Num_Logs FROM V$log_History Vlh GROUP BY To_Char(Vlh.First_Time,  'YYYY-MM-DD'), To_Char(Vlh.First_Time, 'HH24') || ':00') Log_Hist, V$log Vl ,  V$database Vdb WHERE Vl.Group# = 1 ORDER BY Log_Hist.Start_Date, Log_Hist.Start_Time; Redo generated Per day: select trunc(completion_time) rundate ,count(*)  logswitch ,round((sum(blocks*block_size)/1024/1024)) "REDO PER DAY (MB)" from v$archived_log group by trunc(completion_time) order by 1;

Oracle database check db_recovery_file_dest_size usage

db_recovery_file_dest_size usage The following scripts will check space utilization for  db_recovery_file_dest_size : col name     format a32 col size_mb  format 999,999,999 col used_mb  format 999,999,999 col pct_used format 999 select    name,    ceil( space_limit / 1024 / 1024) size_mb,    ceil( space_used / 1024 / 1024) used_mb,    decode( nvl( space_used, 0),0, 0,    ceil ( ( space_used / space_limit) * 100) ) pct_used from     v$recovery_file_dest order by    name desc; ********************************* set lines 100 col name format a60 select    name,    floor(space_limit / 1024 / 1024) "Size MB",    ceil(space_used / 1024 / 1024)   "Used MB", from    v$recovery_file_dest order by    name;

Oracle Database Check the usage of SGA

SQL> show sga Total System Global Area 524288000 bytes Fixed Size                  2046008 bytes Variable Size             423626696 bytes Database Buffers           92274688 bytes Redo Buffers                6340608 bytes SQL> show parameter sga_max_size NAME                                 TYPE        VALUE ------------------------------------ ----------- ------------------------------ sga_max_size                         big integer 500M select value/1024/1024 shared_pool_size from v$parameter where name = 'shared_pool_size'; select * From v$sgastat; select 'Memory Allocation' " " , round(s.sgasize/1024/1024,2) "Total SGA (Mb)" , round(f.bytes/1024/1024,2) " Free (Mb)" , round(f.bytes*100/s.sgasize,2) " Free (%)" from (select sum(bytes) sgasize from sys.v_$sgastat) s , sys.v_$sgastat f where f.name = 'free memory' / select round(used.bytes /1024