Friday, January 26, 2024

SQL TUNING

 


Step by Step: How to troubleshoot a slow running query in Oracle

This is a day to day task of a DBA. Someone from application team comes to our desk and simply says a query is running slow. We may question him on many things but ultimately a DBA has to tune the query at the end.


This is also very popular and known question for the DBA's who are attending interviews. This question is simply asked again and again. I have also been asked this question multiple times. After a pause, interviewer simply asks...so suppose a user comes and reports that his query is running slow, what will be your approach to tune this.


There is no absolute or concrete answer to this question because there might be multiple way to tune a slow running query. Everyone can have a different approach.


So here is my approach:


Very first thing we have to find which type of query is running slow. Whether it is SELECT query of DML statements(insert, update, delete and merge).


So first we will see how to tune a SELECT query


Step 1 – Find the SQL_ID of the slow running query


There could be two possibilities:


 1) Query is still running: If the slow query is still running then we can find the sql_id of the query by using v$session view.


SQL>select sql_id

from v$session

where sid = 3089;

Output:

SQL_ID

—————————————————

g0uubmuvk4uax


2)  Query is completed: It might be query is completed but application team got to know it later that the query was slow and it did not finish in its usual time. Since this query is not running right now, we can’t query v$session to get its information.


So for this we use AWR/ASH report. We ask application team that at what time the query was running and for that duration we generate the AWR. In ASH report we find all kind of information regarding the top SQL’s. Basically we see SQL STATISTIS section of the AWR report. In this section there is SQL ORDERED BY ELAPSED TIME which matters most to us. If the query which is reported by application team is present in this section then we note down the sql_id of the query. Otherwise we generate ASH report for that particular time and get the sql_id.

  

Step 2 – Run the SQL Tuning advisor for that SQL_ID


After finding the sql_id we can run sql tuning advisor on this sql_id.

Use below steps to run the sql tuning advisor and display its output:


1. Create tuning task for specific Sql id:


SET SERVEROUTPUT ON

DECLARE

  l_sql_tune_task_id  VARCHAR2(100);

BEGIN

  l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (

                          sql_id      => 'g0uubmuvk4uax',

                          scope       => DBMS_SQLTUNE.scope_comprehensive,

                          time_limit  => 60,

                          task_name   => 'g0uubmuvk4uax_tuning_task',

                          description => 'Tuning task for statement g0uubmuvk4uax.');

  DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);

END;

/


2. Execute the tuning task:


EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => 'g0uubmuvk4uax_tuning_task');



3. Display the recommendations:


Once the tuning task has executed successfully the recommendations can be displayed using the REPORT_TUNING_TASK function.


SET LONG 10000;

SET PAGESIZE 1000

SET LINESIZE 200


SELECT DBMS_SQLTUNE.report_tuning_task('g0uubmuvk4uax_tuning_task') AS recommendations FROM dual;


SET PAGESIZE 24



Based on the tuning advisor recommendation we have to take corrective actions. These recommendation could be and many more:


1) Gather Statistics

2) Create Index

3) Drop Index

4) Join orders

5) Accept sql profile

6) Create baseline and many more recommnendations


Before applying any corrective action on production, we need to test that in DEV/QA/UAT/TEST environment or we can ask an tuning expert that this is the recommendation. After all the analysis we should apply in the production database.


After corrective action from tuning advisor run the SQL again and see the improvement.


Step 3 - Check the sql plan hash value and pin the good plan:


Sometime SQL tuning advisor does not recommend anything, in that case we have to go for a different approach.


check if there is any change in the sql plan.


set lines 500

set pages 500

col Snap for a25

col SQL_PROFILE for a40

select distinct b.BEGIN_INTERVAL_TIME as Snap, a.PLAN_HASH_VALUE as plan, a.EXECUTIONS_DELTA as EXECUTIONS, a.ELAPSED_TIME_DELTA/1000000 as ELAPSED_SEC, ROWS_PROCESSED_DELTA as "ROWS" , a.ROWS_PROCESSED_DELTA/CASE WHEN a.EXECUTION_DELTA = 0 THEN -1 ELSE a.EXECUTIONS_DELTA END "Avg Rows", a.ELAPSED_TIME_DELTA/1000000/CASE WHEN a. EXECUTION_DELTA = 0 THEN -1 ELSE a.EXECUTION_DELTA END "Avg Elapsed", a.optimizer_cost, a.SQL_PROFILE from DBA_HIST_SQLSTAT a, DBA_HIST_SNAPHOT b where a.SQL_ID = '&sqlid' and a.snap_id = b.snap_id order by b.BEGIN_INTERVAL_TIME


We can also use below query to to find out the sql plan for n number of days:

(Show the plan has value for a given sqlid over a given period)


SET PAUSE ON

SET PAUSE 'Press Return to Continue'

SET PAGESIZE 60

SET LINESIZE 300


SELECT DISTINCT sql_id, plan_hash_value

FROM dba_hist_sqlstat q,

    (

    SELECT /*+ NO_MERGE */ MIN(snap_id) min_snap, MAX(snap_id) max_snap

    FROM dba_hist_snapshot ss

    WHERE ss.begin_interval_time BETWEEN (SYSDATE - &No_Days) AND SYSDATE

    ) s

WHERE q.snap_id BETWEEN s.min_snap AND s.max_snap

  AND q.sql_id IN ( '&SQLID')

/


here we have to supply the value for number of days.


We can see the entire plan for n number of days the query has used. It is not mandatory that plan is changed. Here it also displays which plan takes how much time executes. So if there is change in plan, we should find best plan and pin it. Plan could be changed due to several reasons like change in the sql, due to stats gathering and many more.


Step 4 - Use TOP command to check the CPU usages by various processes:


TOP command is also useful for performance tuning. Many times, in a single server multiple databases are running. It may happen that one database is consuming more server resources than others. So we have to find out which oracle process is consuming more resources and it is related to which database. For this we use  TOP command. If we see there is CPU used by an oracle process is very high then this a matter of subject to worry about.


$top


Output of the top command 

top - 10:56:49 up 18 days, 18:48,  4 users,  load average: 1.02, 0.92, 0.48

Tasks: 180 total,   2 running, 178 sleeping,   0 stopped,   0 zombie

Cpu(s): 49.8%us,  0.5%sy,  0.0%ni, 49.2%id,  0.5%wa,  0.0%hi,  0.0%si,  0.0%st

Mem:   1815256k total,  1771772k used,    43484k free,    66120k buffers

Swap:  2031608k total,   734380k used,  1297228k free,   747740k cached


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

 5946 oracle    25   0  706m 177m 159m R  100 10.0   9:20.26 oracle

 6104 oracle    15   0  2324 1060  800 R    1  0.1   0:00.12 top

31446 oracle    15   0  688m 135m 129m S    0  7.7   0:08.24 oracle

… output truncated …


In the output, we can see that the process with ID 5946 consumes the most CPU (100 percent) and memory (10 percent) and therefore should be the focus of our attention. To find out more about the process, enter the following command at the UNIX prompt: 

$ ps -aef|grep 5946


oracle    5946  5945 63 10:59 ?

00:01:52 oracleD112D2 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))


The output shows the entire description of the process, which is clearly an Oracle “server process”—a process that is created by Oracle Database when a session is established—and that the process has been running for 1 minute and 52 seconds. The next question, then, is which Oracle Database session this process was created for. For that, we should look into another view—V$PROCESS—where the SPID column shows the server process ID. However, this view does not show the session information, so we need to join this view with the familiar V$SESSION view, as follows: 

select sid

from v$session s, v$process p

where p.spid = 5946

and s.paddr = p.addr;


SID

———

37


Once we know the SID, we can get everything we need to know about the session—the user who established the session, the machine it came from, the operating system user, the SQL it is executing, and so on—from the V$SESSION view. To find the SQL being run by session 37, use this query: 

select sql_fulltext

from v$sql l, v$session s

where s.sid = 37

and l.sql_id = s.sql_id;


Here is the output: 

select max(test1.owner)

from test1, test2, test2, test2,

     test2, test2, test2, test2,

     test2, test2, test2, test2,

     test2, test2, test2, test2,

     test2, test2, test2, test2,

     test2, test2, test2, test2;


This SQL is performing multiple Cartesian joins, so it’s no wonder it’s consuming so much CPU and memory. 

Since this session is using most of the CPU, other sessions on the database might be waiting for the CPU to get their job done. But until or unless this session releases the CPU others won't be able to complete their job. So we can kill this high CPU consuming session so that others can complete their execution. And later on we can investigate why this is consuming so much of CPU.


If it is a DML statement then we have check the locking in the database


Step 5 - Find the locking in the database:


The very first step is to find out if there is any locking in the database. Sometime due to locking a session does not get the required resources and the session gets slow.


We can find below command to check locking in the database:


In Standalone:


sql>select s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ') is blocking'

       || s2.username || '@' || s2.machine || '( SID=' || s2.sid || ')' 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;


In RAC:


sql> select s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ') is blocking'

        || s2.username || '@' || s2.machine || '( SID=' || s2.sid || ')' from

       gv$lock l1, gv$session s1, gv$lock l2, gv$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;



Query Output:


S1.USERNAME||'@'||S1.MACHINE||'(SID='||S1.SID||')ISBLOCKING'||S2.USERNAME||'@'||

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

SYS@host1.abc.com ( SID=229) is blockingSYS@host1.abc.com( SID=226)


If we see the locking from above query then we can simply inform to user/application. And if they suggest to kill this blocking session then after killing we can get rid of this slowness.



Step 6 - Check for the wait events:


There could be some wait events on the database. Check for the particular user and session.


Query for displaying sessions, session state, and wait details


col "Description" format a50

select sid,

        decode(state, 'WAITING','Waiting',

                'Working') state,

        decode(state,

                'WAITING',

                'So far '||seconds_in_wait,

                'Last waited '||

                wait_time/100)||

        ' secs for '||event

        "Description"

from v$session

where username = 'ARUP';


Output:


SID   STATE       Description

————— ——————————  ———————————————————————————————————————————————————————

2832  Working     Last waited 2029 secs for SQL*Net message from client

3346  Waiting     So far 743 secs for enq: TX - row lock contention

4208  Waiting     So far 5498 secs for SQL*Net message from client


It clearly shows the state of the sessions: whether they are working or waiting; if they are working, what they were waiting for earlier and for how long; and if they are waiting, what for and for how long.


In many troubleshooting situations, just knowing the SID of each session is not enough. We may need to know other details, such as the client machine the session is connecting from, the user (of both the database and the operating system), and the service name. All of this information is also readily available in the same V$SESSION view we have been using. Let’s briefly examine the columns that provide that information, by running the below query


select SID, osuser, machine, terminal, service_name,

       logon_time, last_call_et

from v$session

where username = 'ARUP';


SID   OSUSER  MACHINE   TERMINAL  SERVICE_NAME  LOGON_TIME LAST_CALL_ET

————— ——————  ———————   ————————  ————————————  —————————— ————————————

3346  oradb   prodb1    pts/5     SYS$USERS     05-FEB-12          6848

2832  oradb   prodb1    pts/6     SERV1         05-FEB-12          7616

4408  ANANDA  ANLAP     ANLAP     ADHOC         05-FEB-12             0


OSUSER. The operating system user as which the client is connected. The output indicates that session 4408 is connected from the ANLAP machine, where a Windows user, ANANDA, has logged in.

MACHINE. The name of the machine where the client is running. This could be the database server itself. For two of the sessions, the machine name shows up as “prodb1.” Session 4408 runs on a different machine—ANLAP—presumably a laptop.

TERMINAL. If the session is connected from a UNIX server, this is the terminal where it runs.

LOGON_TIME. This shows when the session was first connected to the Oracle Database instance.

Using the columns shown in Listing 5, you can get very detailed information on a user’s sessions.

Suppose you receive a complaint that the applications running on the application server named appsvr1 are experiencing performance issues. Listing 6 shows a query against the V$SESSION view—including columns you’ve used in previous queries in this article—for the sessions connected from that machine and the output.

Code Listing 6: Session waits for a specific machine


col username format a5

col program format a10

col state format a10

col last_call_et head 'Called|secs ago' format 999999

col seconds_in_wait head 'Waiting|for secs' format 999999

col event format a50

select sid, username, program,

        decode(state, 'WAITING', 'Waiting',

                'Working') state,

last_call_et, seconds_in_wait, event

from v$session

where machine = 'appsvr1'

/

                                       Called      Waiting

SID   USERNAME  PROGRAM       STATE    secs ago    for secs   EVENT

————— ———————   ———————————   ———————  —————————   ————————   ——————————————————

2832  ARUP      sqlplus.exe   Waiting       152         151   SQL*Net message

                                                              from client

3089  ARUP      sqlplus.exe   Waiting       146         146   enq: TX - row lock

                                                              contention

3346  ARUP      sqlplus.exe   Working        18          49   SQL*Net message

                                                              from clie

History of wait events in a specific session 


set lines 120 trimspool on

col event head "Waited for" format a30

col total_waits head "Total|Waits" format 999,999

col tw_ms head "Waited|for (ms)" format 999,999.99

col aw_ms head "Average|Wait (ms)" format 999,999.99

col mw_ms head "Max|Wait (ms)" format 999,999.99

select event, total_waits, time_waited*10 tw_ms,

       average_wait*10 aw_ms, max_wait*10 mw_ms

from v$session_event

where sid = 37

/



                                  Total      Waited     Average         Max

Waited for                        Waits    for (ms)   Wait (ms)   Wait (ms)

—————————————————————————— ————————————  ———————————  ——————————  —————————

Disk file operations I/O              8         .00         .10         .00

KSV master wait                       2      350.00      173.20      340.00

os thread startup                     1       20.00       19.30       20.00

db file sequential read               5      160.00       32.10       70.00

direct path read                  1,521   51,010.00       33.50      120.00

direct path read temp           463,035  513,810.00        1.10      120.00

direct path write temp               20      370.00       18.70       50.00

resmgr:cpu quantum                   21      520.00       24.60      110.00

utl_file I/O                          8         .00         .00         .00

SQL*Net message to client            20         .00         .00         .00

SQL*Net message from client          20    9,620.00      481.20    9,619.00

kfk: async disk IO              904,818    3,050.00         .00         .00

events in waitclass Other            35       20.00         .70       20.00



Step 7 - Getting the SQL:


Another key piece of performance tuning information is the SQL statement a session is executing, which will provide more insights into the workings of the session. The same V$SESSION view also shows the SQL statement information. The SQL_ID column in the V$SESSION view shows the ID of the last SQL statement executed. W can get the text of that SQL statement from the V$SQL view, using the SQL_ID value. Here is an example of how I have identified the SQL statement executed by the session that appears slow to the user.


select sql_id

from v$session

where sid = 3089;


SQL_ID

—————————————————

g0uubmuvk4uax


set long 99999

select sql_fulltext

from v$sql

where sql_id = 'g0uubmuvk4uax';

SQL_FULLTEXT

————————————————————————————————————————

update t1 set col2 = 'y' where col1 = 1


Step 8 - Data Access issue:


Although locking-related contention is a very common cause, it is not the only cause of performance problems. Another major cause of contention is disk I/O. When a session retrieves data from the database data files on disk to the buffer cache, it has to wait until the disk sends the data. This wait shows up for that session as “db file sequential read” (for index scans) or “db file scattered read” (for full-table scans) in the EVENT column, as shown below:


select event

from v$session

where sid = 3011;


EVENT

—————————————————————————

db file sequential read


When we see this event, we know that the session is waiting for I/O from the disk to complete. To make the session go faster, we have to reduce that waiting period. There are several ways to reduce the wait:


Reduce the number of blocks retrieved by the SQL statement. Examine the SQL statement to see if it is doing a full-table scan when it should be using an index, if it is using a wrong index, or if it can be rewritten to reduce the amount of data it retrieves.


 Place the tables used in the SQL statement on a faster part of the disk. 


Consider increasing the buffer cache to see if the expanded size will accommodate the additional blocks, therefore reducing the I/O and the wait.  


 Tune the I/O subsystem to return data faster.


To find the table causing a wait, we will again use the V$SESSION view. The view’s P1 and P2 columns provide information about the segment the session is waiting for. Below shows a query of P1 and P2, and the output.There are other options as well, but the preceding ones are the most common remediation techniques. The exact activity we undertake depends on our specific situation, but the first technique—reducing the number of blocks retrieved by a SQL statement—almost always works.  When we think about tuning to reduce the number of blocks, we can look at the SQL statement to see which table is being selected from. But what if you see two or more tables in the statement? How do we determine which table is causing the wait?


To find the table causing a wait, we will again use the V$SESSION view. The view’s P1 and P2 columns provide information about the segment the session is waiting for. below query shows a query of P1 and P2, and the output.


Query to  Check data access waits:


select SID, state, event, p1, p2

from v$session

where username = 'ARUP';


SID  STATE     EVENT                   P1 P2

———— ———————   ——————————————————————— —— ————

2201 WAITING   db file sequential read  5 3011




The P1 column shows the file ID, and the P2 column shows the block ID. From that information in the above result, we can get the segment name from the extent information in DBA_EXTENTS, as shown below:


select owner, segment_name

from dba_extents

where file_id = 5

and 3011 between block_id

and block_id + blocks;


OWNER  SEGMENT_NAME

—————— —————————————

ARUP   T1



This shows that the T1 table, owned by ARUP, is being selected from by the disk in the session. We should direct our attention to this table for tuning. We can move the table to a high-speed disk for faster I/O, or, alternatively, We can focus on making I/O in this table faster by making changes that affect this table, such as creating new indexes, creating materialized views, or building a result cache.


These are the just few general guideline. We can enjoy it most when we really face this situation... :)


Suggestions are most welcome!!!


All DBA QUERIES

 user below :-

select owner,object_name,object_type,timestamp from dba_objects where object_name=upper('&object_name') and owner=upper('&owner');
select owner,segment_name,segment_type,(bytes/power(1024,3)) "size_GB" from dba_segments where segment_name=upper('&object_name') and owner=upper('&owner');

to find object level privileges :-
dba_role_privs, dba_sys_privs and dba_tab_privs 

set lines 400;
col owner for a20;
col grantor for a20;
col grantee for a20;
col table_name for a50;
col privilege for a20;
col grantable for a20;
col hierarchy for a20;
select owner,grantor,grantee,table_name,privilege,grantable,hierarchy from dba_tab_privs where table_name=upper('&table_name') and grantee=upper('&grantee');

************************************************************
#!/bin/sh

sysdate=$(date +'%b %d')

ls -lrt /pac/ipagi2d1/bkup/*dbf* | awk '{print $6,$7}'  | while read bkpdates; 
do
if [[ $bkpdates = $sysdate ]]
then 
echo $bkpdates
else
echo "you can remove : $(ls -lrt 
done;

#!/usr/bin/python2.7
import os, time, fnmatch

# raw_input() will do type conversion from console to python interpreter

path=raw_input("Enter absolute path :")
days  = input("Enter number of days older files want to search:")
now = time.time()

for filename in os.listdir(path):
    filestamp = os.stat(os.path.join(path, filename)).st_mtime
    n_days_ago = now - days * 86400
    if os.path.isfile(filename):
      if  filestamp <= n_days_ago :
          if fnmatch.fnmatchcase(filename,'*dbf*'):
                 print(filename)
          else:
                print("not this")
***************************************************************
Network bandwidth for archive log transfer :-
select round(((value/0.70)*8)/1000000) Bandwidth_required_in_MBPS 
from (select 
to_char(begin_time,'DD-MONTH-YYYY HH:MI:SS') begin_time,
to_char(end_time,'DD-MONTH-YYYY HH:MI:SS') end_time,
metric_name,metric_id,metric_unit,round(value) value
from gv$sysmetric_history where metric_name='Redo Generated Per Sec' and 
to_char(begin_time,'DD-MONTH-YYYY HH:MI:SS') <= to_char(sysdate,'DD-MONTH-YYYY HH:MI:SS') and rownum<2 order by begin_time desc);
****************************************************************
KB MB TB ZB 

select (select host_name from v$instance) "Host", 
(select instance_name from v$instance) "instance",
owner,segment_name,
(select to_char(cast(created as timestamp with local time zone), 'DD-MONTH-YYYY hh24:mi:ss TZD yyyy') "created" from dba_objects where object_name='&object_name' and owner='&schema_name') "created",
(select to_char( cast(sysdate as timestamp with local time zone), 'DD-MONTH-YYYY hh24:mi:ss TZD yyyy') from dual) "sysdate",
case 
when bytes between 0 and 1023 then bytes || 'bytes'
when bytes < power(1024,2) then round(bytes / power(1024,1),4) || 'KB'
when bytes < power(1024,3) then round(bytes / power(1024,2),4) || 'MB'
when bytes < power(1024,4) then round(bytes / power(1024,3),4) || 'GB'
when bytes < power(1024,5) then round(bytes / power(1024,4),4) || 'TB'
when bytes < power(1024,6) then round(bytes / power(1024,5),4) || 'PB'
when bytes < power(1024,7) then round(bytes / power(1024,6),4) || 'EB'
when bytes < power(1024,8) then round(bytes / power(1024,7),4) || 'ZB'
when bytes < power(1024,9) then round(bytes / power(1024,8),4) || 'YB'
else 'INVALID VALUE FOR BYTES'
end as bytes_sizes
from dba_segments
where segment_name='&object_name' and owner='&schema_name';
**********************************************************************
DDL DML changes query:-

select owner,object_name,object_type,created,last_ddl_time,timestamp from 
dba_objects where object_name='&table_name' ;

select table_owner,table_name,inserts,updates,deletes,timestamp 
from all_tab_modifications where table_name='&table';

1) To Find Desired Views In Oracle Database :-
select owner,view_name from all_views where view_name like upper('%&view%');

2) choose the desired view from above and then trigger below :-
desc view_name;
**************************************************************************
grants to new user:-

create user books_admin identified by password;
grant below :
grant connect to books_admin;
grant connect, resource, dba to books_admin;  /* if needed */
grant create session grant any privilege to books_admin; 
grant unlimited tablespace to books_admin;

table level privilege:
grant select, insert, update, delete on schema.books to books_admin;
*************************************************************************
old records in tables :-

select created 
from dba_objects/all_objects  
where object_name = <<your_table_name>>
and owner = 'table_owner'
and object_type = 'table_name';

SELECT scn_to_timestamp( ora_rowscn ) last_modified_date,
       ora_rowscn last_modified_scn,<<other columns>>
  FROM <<your table>>; 

SQL> select current_scn from v$database;
SQL> SELECT SCN_TO_TIMESTAMP('1404377619968') FROM dual;

SCN_TO_TIMESTAMP('1404377619968')
---------------------------------------------------------------------------
25.01.19 07:32:12,000000000
***************************************************************************
constraints :-

set lines 400
col constraint_name for a20;
col constraint_type for a20;
col search_condition for a20;
select CONSTRAINT_NAME,CONSTRAINT_TYPE ,SEARCH_CONDITION,validated from USER_CONSTRAINTS where table_name in ('DELTA_SERVICEOBJECT')

select CONSTRAINT_NAME,CONSTRAINT_TYPE ,SEARCH_CONDITION,validated from USER_CONSTRAINTS where owner='GGS_USER';

col owner for a20;
col constraint_name for a20;
col constraint_type for a5;
col table_name for a20;
col status for a20;
col validated for a5;
col invalid for a5;
col index_owner for a20;
col index_name for a20;
select owner,constraint_name,constraint_type,table_name,status,validated,invalid,index_owner,index_name from all_constraints where owner='&username' and table_name='&table';
************************************************************************
ARCHIVE LOG GENERATION :-


************Daily Archive Log Generation****************
SQL> select trunc(COMPLETION_TIME,'DD') Day, thread#, 
round(sum(BLOCKS*BLOCK_SIZE)/1024/1024/1024) GB,
count(*) Archives_Generated from gv$archived_log 
group by trunc(COMPLETION_TIME,'DD'),thread# order by 1;

DAY                     THREAD#         GB ARCHIVES_GENERATED
-------------------- ---------- ---------- ------------------
10-OCT-2016 00:00:00          1         19                233
11-OCT-2016 00:00:00          1         34                417
12-OCT-2016 00:00:00          1         42                522

*************Hourly Archive Log Generation****************
set pages 1000
alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';

select trunc(COMPLETION_TIME,'HH') Hour,thread# , 
round(sum(BLOCKS*BLOCK_SIZE)/1024/1024/1024) GB,
count(*) Archives from gv$archived_log 
group by trunc(COMPLETION_TIME,'HH'),thread#  order by 1 ;



HOUR         THREAD#         GB   ARCHIVES
--------- ---------- ---------- ----------
18-MAR-23          1          0          1
18-MAR-23          1          0          1
18-MAR-23          1          2          5
18-MAR-23          1          0          2
*****************************************************
DELETE OLD RECORDS FROM TABLES :-

DELETE FROM country WHERE trunc(RUN_DATE) = To_date('21-NOV-17','DD-MON-YY'); --------------------------> ignores index time
DELETE FROM country WHERE RUN_DATE >= date '2017-11-21' and RUN_DATE < date '2017-11-22';  ---------------------------------> best for performance 
DELETE FROM country WHERE RUN_DATE  BETWEEN TO_DATE('28/02/2014', 'DD/MM/YYYY') AND TO_DATE('20/06/2014', 'DD/MM/YYYY');
***************************************************************
User Grants :-

User creation:

select dbms_metadata.get_ddl( 'USER', 'PHIL' ) from dual;
Default role:

select dbms_metadata.get_granted_ddl( 'DEFAULT_ROLE', 'PHIL' ) from dual;
System grants:

select dbms_metadata.get_granted_ddl( 'SYSTEM_GRANT', 'PHIL' ) from  dual;
Object grants:

select dbms_metadata.get_granted_ddl( 'OBJECT_GRANT', 'PHIL' ) from dual;
Role grants:

select dbms_metadata.get_granted_ddl( 'ROLE_GRANT', 'PHIL' ) from dual;
Quotas:

select dbms_metadata.get_granted_ddl( 'TABLESPACE_QUOTA', 'PHIL' ) from dual;
******************************************************************************
There are 3 options for SCOPE parameter:

1. MEMORY – the change is immediate but will not be available post instance restart
2. SPFILE – the changes will be made to spfile, however it will be applied the database, post instance restart
3. BOTH – Changes will be applied to database immediate, And it dont needs database restart

FOR RAC:
alter system set job_queue_processes=500 scope=both sid='ORCL1';
alter system set job_queue_processes=500 scope=both sid='*';  ------------------------------> for all instances in RAC DB
************* alter system set parameter_name=value scope=both or spfile or memory  sid='instance_name or *'; **************************
******************************************************************************
RMAN BACKUP SHELL SCRIPT :-

#!/bin/bash

bkuploc=$(grep -o "\w*/[[:graph:]]*" bkuploc.txt)
files=$(date -d '-1 day' +%Y_%m_%d)

sqlplus / as sysdba << !!
spool bkuploc.txt
col value_col_plus_show_param for a80;
show parameter db_recovery_file_dest;
spool off
exit;
!!


process=$(ps -ef | grep -i rman | wc -l )

if [ $process -gt 2 ]
then
        ls $bkuploc/$files*
        mail -s "rman backup running" km00780716@techmahindra.com
else
        ls -lrt $bkuploc/$files* | mail -s "rman not  running" km00780716@techmahindra.com
fi
*************************************************************************
SYSTEM EVENTS IN ORACLE DATABASE:-
***********************************************************************************
select
     inst_id,
     event,
     total_waits,
     time_waited
  from
     gv$system_event
  where
     event in ('gc current block lost',
               'gc cr block lost')
  order by
     event,
     inst_id;

 

   INST_ID EVENT                          TOTAL_WAITS TIME_WAITED
---------- ------------------------------ ----------- -----------
         1 gc cr block lost                        50        3029
         2 gc cr block lost                        75        4516
         1 gc current block lost                   26        1467
         2 gc current block lost                   36        2060
 
*************************************************************************************
select
     sn.inst_id,
     sn.name,
     ss.value
  from
     gv$statname sn,
     gv$sysstat ss
  where
     sn.inst_id = ss.inst_id
     and
     sn.statistic# = ss.statistic#
     and
     sn.name = 'gc blocks lost'
  order by
  sn.inst_id;
 
   INST_ID NAME                 VALUE
---------- -------------------- ----------
         1 gc blocks lost               90
         2 gc blocks lost              164
***************************************************************
Check Current User Permission
------------------------------------------------------
select * from USER_ROLE_PRIVS where USERNAME=USER;
select * from USER_TAB_PRIVS where Grantee = USER;
select * from USER_SYS_PRIVS where USERNAME = USER;
----------------------------------------------------------------
To Check the roles granted to a user:
--------------------------------------
select * from dba_role_privs where grantee = 'username';
select * from dba_tab_privs where grantee = 'username';
select * from dba_sys_privs where grantee = 'username';
------------------------------------------------------------------
********************************************************************
GOLDEN GATE XID :-

The 3 part XID as in showtrans as these     ......................username: ggsuser Passwd: GOLDENGATE4U   ......on nmsis8d1        

select t.xidusn||'.'||t.xidslot||'.'||t.xidsqn xid from v$transaction t; .........................best query 

to find SID SERIAL:                 ..............................................................best query

select  t.start_time,t.status TSTATUS, s.status SSTATUS,s.sid, s.serial# ,s.machine , s.sql_id,s.prev_sql_id,s.process,t.XIDUSN||'.'||t.XIDSLOT||'.'||t.XIDSQN XID from gv$transaction t, gv$session s  where t.addr=s.taddr and t.inst_id=s.inst_id and t.start_date < (sysdate-1/142) order  by t.start_time;

###############################################################
-- if needed, you can go ahead and kill the sql (if it is not of a major impact)

alter system kill session '9871,167';

------------------------------------------------------------
XID:                  8805.6.296139
Items:                1       
Extract:              EXRAJ   
Redo Thread:          2     
Start Time:           2013-05-10:21:24:33 
SCN:                  1586.3896755063 (6815714886519) 
Redo Seq:             79547
Redo RBA:             791874576         
Status:               Running           



SQL> select * from gv$transaction where xidusn=8805;

SQL> select sid,serial#,event,machine,sql_id,seconds_in_wait,prev_sql_id,module,program,action from gv$session where taddr='0000001BFF3DEBD8';

 SQL> select
hash_value, address,
executions,buffer_gets, disk_reads,
round(buffer_gets/decode(executions, 0, 1, executions), 1) avg_gets,
round(disk_reads/decode(executions, 0, 1, executions), 1) avg_disk,
last_load_time,
module,
sql_fulltext
from v$sqlarea
where sql_id='&sql_id';

SQL>
select logon_time,status,LAST_CALL_ET from gv$session where sid=9871 and inst_id=2;

**************************************************************************

Oracle Database objects like packages, procedures, procedure columns, functions, indexes, tables, schemas, views

Tables :-
select table_name,owner from sys.all_tables order by owner,table_name;

select table_name,owner from sys.all_tables where owner='schema_name' order by table_name;

Schemas:-
select username from sys.all_users order by username;

Views :-
select view_name,owner from sys.all_views order by owner,view_name;

Packages:-
select object_name,owner from sys.all_objects where upper(object_type) =upper('PACKAGE')
order by owner, object_name;

Procedures:-
select object_name,owner from sys.all_objects where upper(object_type) =upper('PROCEDURE')
order by owner,object_name;

Procedure Columns:-
select owner,object_name,argument_name,data_type,in_out from sys.all_arguments
order by owber,object_name,sequence;

Functions:-
select object_name,owner from sys.all_objects where upper(object_type) = upper('FUNCTION')
order by owner,object_name;

Indexes:-
select index_name,table_name,table_owner from sys.all_indexes order by table_owner,table_name,index_name;


Nonschema objects :-
  • Contexts
  • Directories
  • Editions
  • Flashback archives
  • Lockdown profiles
  • Profiles
  • Restore points
  • Roles
  • Rollback segments
  • Tablespaces
  • Tablespace sets
  • Unified audit policies
  • Users

Schema objects:-

  • Analytic views
  • Attribute dimensions
  • Clusters
  • Constraints
  • Database links
  • Database triggers
  • Dimensions
  • External procedure libraries
  • Hierarchies
  • Index-organized tables
  • Indexes
  • Indextypes
  • Java classes
  • Java resources
  • Java sources
  • Join groups
  • Materialized views
  • Materialized view logs
  • Mining models
  • Object tables
  • Object types
  • Object views
  • Operators
  • Packages
  • Sequences
  • Stored functions
  • Stored procedures
  • Synonyms
  • Tables
  • Views
  • Zone maps

all_dependencies
all_db_links
all_directories
all_errors
all_goldengate_rules
all_goldengate_privileges
all_jobs
all_libraries
all_lobs
all_mviews
all_objects
all_blockchain_tables
all_catalog
all_certificates
all_constraints
all_credentials
gv$session
gv$session_longops

Wednesday, January 24, 2024

LOGS :----->CRS, RDBMS, PDBS, ASM LOGS LOCATION ?

 That's all you need:

# Alert Logs

tail -n 1000 ${ORACLE_BASE}/diag/rdbms/<dbname>/<instance_name>/trace/alert_<instance_name>.log

# Listener Logs

tail -n 1000 ${ORACLE_BASE}/diag/tnslsnr/$(hostname)/listener/trace/listener.log

# Clusterware Logs

tail -n 1000 ${GRID_HOME}/log/$(hostname)/alert$(hostname).log


=> CRS: 

$ORACLE_BASE/diag/crs/$(hostname)/crs/trace/alert.log

=> ASM: 

$ORACLE_BASE/diag/+asm/<ASM_SID>/trace/alert_<ASM_SID>.log

=> RDBMS-Instances: $ORACLE_BASE/rdbms/<DB_NAME>/<DB_SID>/trace/alert_<DB_SID>.log

=> PDBs: There is not specific log for PDBS. Please see the alert.log of the corresponding RDBMS instances


 Locations of Oracle Clusterware Component Log Files

best :- ${GRID_HOME}/log/$(hostname)

ComponentLog File LocationFoot 1 

Cluster Ready Services Daemon (CRSD) Log Files

Grid_home/log/host_name/crsd

Cluster Synchronization Services (CSS)

Grid_home/log/host_name/cssd

Cluster Time Synchronization Service (CTSS)

Grid_home/log/host_name/ctssd

Grid Plug and Play

Grid_home/log/host_name/gpnpd

Multicast Domain Name Service Daemon (MDNSD)

Grid_home/log/host_name/mdnsd

Oracle Cluster Registry

Oracle Cluster Registry tools (OCRDUMP, OCRCHECK, OCRCONFIG) record log information in the following location:

Grid_home/log/host_name/client

Cluster Ready Services records Oracle Cluster Registry log information in the following location:

Grid_home/log/host_name/crsd

Oracle Grid Naming Service (GNS)

Grid_home/log/host_name/gnsd

Oracle High Availability Services Daemon (OHASD)

Grid_home/log/host_name/ohasd

Event Manager (EVM) information generated by evmd

Grid_home/log/host_name/evmd

Oracle RAC RACG

The Oracle RAC high availability trace files are located in the following two locations:

Grid_home/log/host_name/racg
$ORACLE_HOME/log/host_name/racg

Core files are in subdirectories of the log directory. Each RACG executable has a subdirectory assigned exclusively for that executable. The name of the RACG executable subdirectory is the same as the name of the executable.

Additionally, you can find logging information for the VIP and database in these two locations, respectively.

Server Manager (SRVM)

Grid_home/log/host_name/srvm

Disk Monitor Daemon (diskmon)

Grid_home/log/host_name/diskmon

Grid Interprocess Communication Daemon (GIPCD)

Grid_home/log/host_name/gipcd

Monday, January 22, 2024

Listener error :- listener know no service

[oracle@pm ~]$ cat /u02/app/oracle/homes/OraDB21Home1/network/admin/listener.ora

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = pm)(PORT = 1522))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1522))
    )
  )



ADR_BASE_LISTENER = /u02/app/oracle

 oracle@pm ~]$ lsnrctl status


LSNRCTL for Linux: Version 21.0.0.0.0 - Production on 22-JAN-2024 23:09:56
Copyright (c) 1991, 2021, Oracle.  All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=pm)(PORT=1522)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 21.0.0.0.0 - Production
Start Date                22-JAN-2024 23:02:59
Uptime                    0 days 0 hr. 6 min. 56 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u02/app/oracle/homes/OraDB21Home1/network/admin/listener.ora
Listener Log File         /u02/app/oracle/diag/tnslsnr/pm/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=pm.shaikh.com)(PORT=1522)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1522)))
listener currently know no service...

follow below steps:-
=================
SQL> alter system set local_listener='(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=pm.shaikh.com)(PORT=1522)))';

SQL> alter system register;
SQL> startup force;

$ lsnrctl reload 
$ lsnrctl status




netca 
ipc protocol key = extproc
tcp as it is 

Friday, January 19, 2024

How to comment tables in oracle database ?

# How to comment oracle database #
---------------------------------------------------------------------------------------------------------
COMMENT ON TABLE your_table_name
IS 'This is a multi-line comment for your table.
It provides additional information about the table structure and purpose.';


SELECT table_name, comments
FROM all_tab_comments
WHERE table_name = 'your_table_name';

Monday, January 15, 2024

Server patching Database patching on Production server

* Server patching or upgrades * 
--------------------------------------------
apps down 
database down 
sa reboot server / patching/upgrades
database up
apps up
---------------------------------------------
 
* Database patching/upgrades Server patching/upgrades *
----------------------------------------------------------------------
apps down
gg down
database down
sa reboot server/ patching/upgrades
database up
apps up 
gg up 
----------------------------------------------------------------------

EXPDP & IMPDP

 How to find failed tables after export/import job has done on Oracle Database ?


cat expdp.log | grep -i "error" | grep -o '\"[[:graph:]]\{0,255\}\".\"[[:graph:]]\{0,255\}\"' > failed_tables.txt


it'll show failed tables having formatted in the expdp.log file as below :-
"schema"."table_name"


Hi Team, Please use these steps for schema refresh when export is perform by normal exp/imp utlity. Step 1:- Take a export using expdp of user that needs to refresh. Example :- Expdp system/xyz directory=DPMUP dumpfile=dmp_file_name_%U.DMP LOGFILE=dmp_file_name_IMP_EXP.LOG SCHEMAS=user1,user2 Step 2:- drop the user.( make sure app is down ). Step 3:- import the metadata only from dumpfile ( created in step1 ). Example :- impdp system/xyz directory=DPMUP dumpfile=dmp_file_name_%U.DMP LOGFILE=dmp_file_name_IMP_EXP.LOG REMAP_SCHEMA=source_schema:target_schema,source_schema:target_schema CONTENT=METADATA_ONLY EXCLUDE=TABLE Note:- exclude table else you will get error like this during data import. ORA-02291: integrity constraint (owner.FK79B62C533C17239) violated - parent key not found Or you need to disable all constraints manually before data import. Step 4:- crosscheck for any missing role from source schema. SELECT * FROM dba_role_privs where GRANTEE in(‘owner'); --- on source. GRANTEE GRANTED_ROLE ADM DEF ------------------------------ ------------------------------ --- --- owner APPLICATION_DEVELOPER NO YES SQL >SELECT * FROM dba_role_privs where GRANTEE='owner_schema'; --- on target. GRANTEE GRANTED_ROLE ADM DEF ------------------------------ ------------------------------ --- --- owner1 APPLICATION_CREATOR NO YES owner1 NEWT_SYSPRIV NO YES this is the missing role ( APPLICATION_DEVELOPER ) on target. SQL >grant APPLICATION_DEVELOPER to schema; Step 5:- Check for the tablespace used by source schema. SQL >select distinct tablespace_name from dba_segments where owner='schema'; ---- On target. TABLESPACE_NAME ------------------------------ ts1
SQL>select distinct tablespace_name from dba_segments where owner='schema'; ----- On source. TABLESPACE_NAME ------------------------------ t1
t2 Target schema don’t have quota on users in this case. SQL >alter user schema quota unlimited on users; User altered. Step 6:- This is the last step ,now we are good to start import. imp system/cowboy01 file=dmp_file_%U.dmp fromuser=source_user touser=target_user log=dmp_file_name.log ignore=y STATISTICS=NONE


USERID=system/your_password
DIRECTORY=DATA_PUMP_DIR
DUMPFILE=exp_objects.dmp
LOGFILE=exp_objects.log
SCHEMAS=HR
INCLUDE=TABLE,INDEX,VIEW,SEQUENCE,CONSTRAINT,SYNONYM,ROLE_GRANT,SYSTEM_GRANT,
OBJECT_GRANT

Enable OpenSSH on Windows 11

Step 1: Install OpenSSH Server You can do this via PowerShell (run as Administrator ): Check if it's already available: Get-WindowsCapab...