Blog

Blog
Affichage des articles dont le libellé est Monitoring. Afficher tous les articles
Affichage des articles dont le libellé est Monitoring. Afficher tous les articles

Statspack ou l'ancêtre d'AWR

Hé oui, statspack a été remplacé par AWR (Automatic Workload Repository), mais cette fonctionnalité fait partie du diagnostic pack qui est une option même pour la version Enterprise. (Il faut d'ailleurs faire un peu attention, car cette fonctionnalité est installée même si elle n'a pas été payée...)
Pour ne pas payer ou risquer d'être en infraction, il reste le statspack. je n'ai aps trouvé de vraie doc sur ce statspck en 11g, mais sachez que la doc 9i est toujours d'actualité.

Installer Statspack

Hé oui, contrairement à AWR, il faut l'installer avant de l'utiliser. Autant vous dire que vous ne pourrez jamais sortir un rapport sur ce qu'il s'est passé hier sur la base de production...
Pour installer statspack, il suffit de lancer le script spcreate.sql qui se trouve sous $ORACLE_HOME/rdbms/admin.
sqlplus / as sysdba @?/rdbms/admin/spcreate
Le script devrait vous demander certaines informations comme le mot de passe du user perfstat, le tablespace d'espace temporaire et le tablespace par défaut du user perfstat.

Et c'est tout!

Faire un snapshot

Pour faire un snapshot, il suffit de lancer le script suivant (après s'être connecté avec le user perfstat) :
EXECUTE statspack.snap;

Faire un rapport

Pour faire un rapport, il faut lancer le script suivant (toujours connecté avec le user perfstat) :
@?/rdbms/admin/spreport
Ensuite, on peut analyser plus avant un ordre SQL en fournissant le hash value de la requête SQL au script suivant
@?/rdbms/admin/sprepsql

Programmer des snapshots réguliers

Comme on ne prévient pas quand on va en avoir besoin, il vaut mieux passer régulièrement des snapshots. Pour ça, on peut soit créer un script qui génère les snapshots et le lancer via un scheduler quelconque, soit utiliser Oracle pour les lancer. je préfère utiliser Oracle :-). En 9i, on utilisera DBMS_JOB, à partir de la 10g, on préfèrera DBMS_SCHEDULER.

Surveiller l'activité d'une base

Un collègue vient de me passer une requête magique pour suivre un peu mieux l'activité d'une base en fonction du nombre de switch d'archives log. (Bien sûr si votre base n'est pas en mode archive log, c'est pas la peine.)
set lines 120;
set pages 999;
SELECT * FROM (
SELECT * FROM (
SELECT TO_CHAR(FIRST_TIME, 'DD/MM') AS "DAY" 
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '00', 1, 0)), '99') "00" 
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '01', 1, 0)), '99') "01"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '02', 1, 0)), '99') "02"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '03', 1, 0)), '99') "03"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '04', 1, 0)), '99') "04"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '05', 1, 0)), '99') "05"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '06', 1, 0)), '99') "06"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '07', 1, 0)), '99') "07"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '08', 1, 0)), '99') "08"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '09', 1, 0)), '99') "09"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '10', 1, 0)), '99') "10"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '11', 1, 0)), '99') "11"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '12', 1, 0)), '99') "12"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '13', 1, 0)), '99') "13"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '14', 1, 0)), '99') "14"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '15', 1, 0)), '99') "15"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '16', 1, 0)), '99') "16"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '17', 1, 0)), '99') "17"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '18', 1, 0)), '99') "18"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '19', 1, 0)), '99') "19"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '20', 1, 0)), '99') "20"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '21', 1, 0)), '99') "21"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '22', 1, 0)), '99') "22"
, TO_CHAR(SUM(DECODE(TO_CHAR(FIRST_TIME, 'HH24'), '23', 1, 0)), '99') "23"
FROM V$LOG_HISTORY
WHERE extract(year FROM FIRST_TIME) = extract(year FROM sysdate) 
GROUP BY TO_CHAR(FIRST_TIME, 'DD/MM')
) ORDER BY TO_DATE(extract(year FROM sysdate) || DAY, 'YYYY DD/MM') DESC
) WHERE ROWNUM < 8 
Oui, ça fait peur, mais c'est très efficace!

Espace occupé par une base de données Oracle

je compile ici deux requêtes très intéressante pour surveiller l'espace occupé par une base de données Oracle.

ASM

Si vous êtes sous ASM, vous pouvez surveiller l'espace occupé sur chaque diskgroup (Les données étant load balancées, je ne vois pas trop l'intérêt de travailler sur l'espace occupé dans chaque disque).
SET LINES 200
SET PAGES 100
COL dg_name FORMAT A20
COL d_name FORMAT A20
COL action FORMAT A20
COL etat FORMAT A20
COL path FORMAT A30
COL size_mb FORMAT 9999
COL free_mb FORMAT 9999

SELECT NVL(adg.name,'n/a') dg_name,
ROUND(SUM(ad.TOTAL_MB/1024)) SIZE_GB,
ROUND(SUM(ad.FREE_MB/1024)) FREE_GB,
ROUND(SUM(ad.TOTAL_MB/1024))-ROUND(SUM(ad.FREE_MB/1024)) USED_GB
FROM v$asm_diskgroup adg LEFT JOIN v$asm_disk ad ON ad.group_number = adg.group_number
WHERE ad.header_status <> 'foreign'
GROUP BY NVL(adg.name,'n/a')

Tablespaces

Si vous n'êtes pas sous ASM, l'espace pris sur le disque n'est pas un bon indicateur étant donné que l'espace alloué dans les tablespaces est considéré par l'OS comme occupé alors qu'Oracle peut très bien ne pas l'utiliser...

J'ai récupéré cette requête auprès d'une collègue qui elle même la tenait d'un collègue etc... Bref, je ne connais pas l'auteur de cette requête s'il se reconnaît et désire que je la supprime, il lui suffit de me contacter...
set pagesize 1000
set linesize 150

select  SUBSTR(ORA_DATABASE_NAME,0,32) as DATABASE_NAME,
SUBSTR(HOST_NAME,0,32) as HOST_NAME,
USER,
to_char(SYSDATE,'YYYY-MM-DD hh24 :mi') as CUR_DATE
from v$instance ;


set echo off ;



col STATUT       for A20        head "STATUT"             wrap
col tbsName      for A25        head "TABLESPACE"         wrap
col prmType      for A1         head "T"                  trunc
col extMan       for A1         head "X"                  trunc
col tbsStat      for A2         head "On"                 trunc
col tbsMsize     for 999,990    head "TAILLE|Allouée|(M)" trunc
col tbsMsizeMax  for 999,990    head "TAILLE|Limite|(M)"  trunc
col usedSize     for 999,990    head "VOLUME|Utilise|(M)" trunc
col usedPct      for 999.99     head "VOLUME|/alloué|(%)" trunc
col usedTotPct   for 999.99     head "VOLUME|/limite|(%)" trunc

select
--decode( greatest(90,nvl(t.BYTES/a.BYTES*100,0)), 90, 'TAILLE_TBS_OK', 'WARNING_TBS_FULL' ) STATUT,
case
when d.TABLESPACE_NAME like 'SYS%'                            then '   NO_CHECK'
when 
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl((a.BYTES - NVL(f.BYTES, 0)) / nvl(w.BYTES, 0) * 100, 0)
else nvl((a.BYTES - NVL(f.BYTES, 0)) / a.BYTES * 100, 0)
end > 95
then '!! ALERT_TBS   > 95%'
when 
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl((a.BYTES - NVL(f.BYTES, 0)) / nvl(w.BYTES, 0) * 100, 0)
else nvl((a.BYTES - NVL(f.BYTES, 0)) / a.BYTES * 100, 0)
end > 85
then '!  WARNING_TBS > 85%'
else '   TBS_SIZE_OK'
end STATUT,
d.TABLESPACE_NAME                                   tbsName,
decode (d.CONTENTS, 'PERMANENT', 'P',
'TEMPORARY', 'T',
'UNDO', 'U')               prmType,
decode (d.EXTENT_MANAGEMENT, 'LOCAL', 'L', 'D')     extMan,
decode (d.STATUS, 'ONLINE', ' Y', ' N')             tbsStat,
nvl(a.BYTES /1024/1024, 0)                          tbsMsize,
nvl(w.BYTES /1024/1024, 0)                       tbsMsizeMax,
nvl(a.BYTES - nvl(f.BYTES, 0), 0)/1024/1024         usedSize,
nvl((a.BYTES - NVL(f.BYTES, 0)) / a.BYTES * 100, 0) usedPct,
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl((a.BYTES - NVL(f.BYTES, 0)) / nvl(w.BYTES, 0) * 100, 0) 
else nvl((a.BYTES - NVL(f.BYTES, 0)) / a.BYTES * 100, 0)
end usedTotPct
from DBA_TABLESPACES d,
(select TABLESPACE_NAME, sum(BYTES) bytes
from DBA_DATA_FILES
group by TABLESPACE_NAME) a,
(select TABLESPACE_NAME, sum(BYTES) bytes
from DBA_FREE_SPACE
group by TABLESPACE_NAME) f,
(select TABLESPACE_NAME, sum(case when (AUTOEXTENSIBLE='YES') then MAXBYTES else BYTES end) bytes
from DBA_DATA_FILES group by TABLESPACE_NAME) w 
where d.TABLESPACE_NAME = a.TABLESPACE_NAME(+)
and d.TABLESPACE_NAME = f.TABLESPACE_NAME(+)
and d.TABLESPACE_NAME = w.TABLESPACE_NAME(+)
and not (d.EXTENT_MANAGEMENT = 'LOCAL' and d.CONTENTS = 'TEMPORARY')
union all
select
--decode( greatest(90,nvl(t.BYTES/a.BYTES*100,0)), 90, 'TAILLE_TBS_OK', 'WARNING_TBS_FULL' ) STATUT,
case
when d.TABLESPACE_NAME like 'SYS%'                            then '   NO_CHECK'
when 
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl(t.BYTES / nvl(w.BYTES, 0) * 100, 0)
else nvl(t.BYTES / a.BYTES * 100, 0)
end > 95
then '!! ALERT_TBS   > 95%'
when
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl(t.BYTES / nvl(w.BYTES, 0) * 100, 0)
else nvl(t.BYTES / a.BYTES * 100, 0)
end > 85
then '!  WARNING_TBS > 85%'
else '   TBS_SIZE_OK'
end STATUT,
d.TABLESPACE_NAME                                   tbsName,
decode (d.CONTENTS, 'PERMANENT', 'P',
'TEMPORARY', 'T',
'UNDO', 'U')               prmType,
decode (d.EXTENT_MANAGEMENT, 'LOCAL', 'L', 'D')     extMan,
decode (d.STATUS, 'ONLINE', ' Y', ' N')             tbsStat,
nvl(a.BYTES / 1024 / 1024, 0)                       tbsMsize,
nvl(w.BYTES /1024/1024, 0)                       tbsMsizeMax,
nvl(t.BYTES, 0)/1024/1024                           usedSize,
nvl(t.BYTES / a.BYTES * 100, 0)                     usedPct,
case
when nvl(w.BYTES /1024/1024, 0) != 0 then nvl(t.BYTES / nvl(w.BYTES, 0) * 100, 0)
else nvl(t.BYTES / a.BYTES * 100, 0)
end usedTotPct
from DBA_TABLESPACES d,
(select TABLESPACE_NAME, sum(BYTES) bytes
from DBA_TEMP_FILES
group by TABLESPACE_NAME) a,
(select TABLESPACE_NAME, sum(BYTES_CACHED) bytes
from V$TEMP_EXTENT_POOL
group by TABLESPACE_NAME) t,
(select TABLESPACE_NAME, sum(case when (AUTOEXTENSIBLE='YES') then MAXBYTES else BYTES end) bytes
from DBA_DATA_FILES group by TABLESPACE_NAME) w 
where d.TABLESPACE_NAME = a.TABLESPACE_NAME(+)
and d.TABLESPACE_NAME = t.TABLESPACE_NAME(+)
and d.TABLESPACE_NAME = w.TABLESPACE_NAME(+)
and d.EXTENT_MANAGEMENT = 'LOCAL'
and d.CONTENTS = 'TEMPORARY'
order by 1 desc, 2 asc;
Ouais, je sais, cette requête est mortelle ;-)