2026-03-12 20:23:15
This commit is contained in:
123
tpt/tools/collectors/latchprof_install.sql
Normal file
123
tpt/tools/collectors/latchprof_install.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- LatchProfX collector v2.0 by Tanel Poder (blog.tanelpoder.com)
|
||||
|
||||
-- drop table latchprof_reasons;
|
||||
|
||||
create table latchprof_reasons (
|
||||
indx number not null
|
||||
, reason_name varchar2(200) not null
|
||||
, reason_label varchar2(200)
|
||||
, primary key (indx)
|
||||
)
|
||||
organization index
|
||||
tablespace users
|
||||
/
|
||||
|
||||
insert into latchprof_reasons (indx,reason_name,reason_label)
|
||||
select indx, ksllwnam, ksllwlbl
|
||||
from x$ksllw
|
||||
/
|
||||
|
||||
commit;
|
||||
|
||||
--drop table latchprof_history;
|
||||
|
||||
create table latchprof_history
|
||||
tablespace users
|
||||
as
|
||||
select
|
||||
systimestamp sample_timestamp
|
||||
, lh.ksuprpid pid
|
||||
, lh.ksuprsid sid
|
||||
, lh.ksuprlat child_address
|
||||
, lh.ksuprlnm latch_name
|
||||
, lh.ksuprlmd hold_mode
|
||||
, lh.ksulawhr where_location
|
||||
, lh.ksulawhy which_object
|
||||
, s.ksusesqh sqlhash
|
||||
, s.ksusesql sqladdr
|
||||
, s.ksusesph planhash
|
||||
, s.ksusesch sqlchild
|
||||
, s.ksusesqi sqlid
|
||||
from
|
||||
x$ksuprlat lh
|
||||
, x$ksuse s
|
||||
where
|
||||
lh.ksuprsid = s.indx
|
||||
and 1=0
|
||||
/
|
||||
|
||||
|
||||
create or replace package latchprof as
|
||||
procedure snap_latchholder(p_sleep in number default 1);
|
||||
end latchprof;
|
||||
/
|
||||
show err
|
||||
|
||||
create or replace package body latchprof as
|
||||
|
||||
procedure snap_latchholder(p_sleep in number default 1) as
|
||||
begin
|
||||
|
||||
while true loop
|
||||
|
||||
insert into latchprof_history
|
||||
select /*+ LEADING(lh) USE_NL(s) LATCHPROF_INSERT */
|
||||
systimestamp sample_timestamp
|
||||
, lh.ksuprpid pid
|
||||
, lh.ksuprsid sid
|
||||
, lh.ksuprlat child_address
|
||||
, lh.ksuprlnm latch_name
|
||||
, lh.ksuprlmd hold_mode
|
||||
, lh.ksulawhr where_location
|
||||
, lh.ksulawhy which_object
|
||||
, s.ksusesqh sqlhash
|
||||
, s.ksusesql sqladdr
|
||||
, s.ksusesph planhash
|
||||
, s.ksusesch sqlchild
|
||||
, s.ksusesqi sqlid
|
||||
from
|
||||
x$ksuprlat lh
|
||||
, x$ksuse s
|
||||
where
|
||||
lh.ksuprsid = s.indx
|
||||
;
|
||||
commit;
|
||||
|
||||
dbms_lock.sleep(p_sleep);
|
||||
|
||||
end loop; -- while true
|
||||
|
||||
end snap_latchholder;
|
||||
|
||||
end latchprof;
|
||||
/
|
||||
show err
|
||||
|
||||
-- 9i version
|
||||
create or replace view latchprof_view as
|
||||
select
|
||||
h.sample_timestamp
|
||||
, h.pid
|
||||
, h.sid
|
||||
, h.child_address
|
||||
, h.latch_name
|
||||
, h.hold_mode
|
||||
, h.where_location
|
||||
, h.which_object
|
||||
, h.sqlid
|
||||
, h.sqlchild
|
||||
, h.planhash
|
||||
, h.sqlhash
|
||||
, h.sqladdr
|
||||
, r.reason_name
|
||||
, r.reason_label
|
||||
from
|
||||
latchprof_history h
|
||||
, latchprof_reasons r
|
||||
where
|
||||
h.where_location = r.indx
|
||||
/
|
||||
|
||||
58
tpt/tools/collectors/mutexprof_install.sql
Normal file
58
tpt/tools/collectors/mutexprof_install.sql
Normal file
@@ -0,0 +1,58 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
drop table mutexprof_history;
|
||||
|
||||
create table mutexprof_history
|
||||
tablespace users
|
||||
as
|
||||
select
|
||||
*
|
||||
from
|
||||
x$mutex_sleep_history
|
||||
where
|
||||
1=0
|
||||
/
|
||||
|
||||
create or replace package mutexprof as
|
||||
procedure snap_mutex_sleeps(p_sleep in number default 1);
|
||||
end mutexprof;
|
||||
/
|
||||
show err
|
||||
|
||||
create or replace package body mutexprof as
|
||||
|
||||
procedure snap_mutex_sleeps(p_sleep in number default 1) as
|
||||
lv_max_sleep_timestamp timestamp := systimestamp;
|
||||
type typ is table of x$mutex_sleep_history%rowtype;
|
||||
t typ;
|
||||
begin
|
||||
|
||||
while true loop
|
||||
|
||||
select * bulk collect into t
|
||||
from x$mutex_sleep_history
|
||||
where sleep_timestamp > lv_max_sleep_timestamp;
|
||||
|
||||
-- get max timestamp so next time we can ignore these rows
|
||||
for r in 1 .. t.count loop
|
||||
if t(r).sleep_timestamp > lv_max_sleep_timestamp then
|
||||
lv_max_sleep_timestamp := t(r).sleep_timestamp;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
-- insert
|
||||
forall r in 1 .. t.count
|
||||
insert into mutexprof_history values t(r);
|
||||
|
||||
commit;
|
||||
dbms_lock.sleep(p_sleep);
|
||||
|
||||
end loop; -- while true
|
||||
|
||||
end snap_mutex_sleeps;
|
||||
|
||||
end mutexprof;
|
||||
/
|
||||
show err
|
||||
|
||||
109
tpt/tools/collectors/plancap_collector.sql
Normal file
109
tpt/tools/collectors/plancap_collector.sql
Normal file
@@ -0,0 +1,109 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
CREATE OR REPLACE PACKAGE plancap_collector AS
|
||||
|
||||
PROCEDURE snap_data_files;
|
||||
PROCEDURE snap_free_space;
|
||||
PROCEDURE snap_segment_space;
|
||||
PROCEDURE snap_service_stats;
|
||||
|
||||
END plancap_collector;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE PACKAGE BODY plancap_collector AS
|
||||
|
||||
PROCEDURE snap_data_files AS
|
||||
BEGIN
|
||||
INSERT INTO plancap$data_files
|
||||
SELECT
|
||||
sysdate
|
||||
, tablespace_name
|
||||
, file_id
|
||||
, SUM(bytes)
|
||||
, SUM(blocks)
|
||||
, relative_fno
|
||||
FROM
|
||||
dba_data_files
|
||||
GROUP BY
|
||||
sysdate, tablespace_name, file_id, relative_fno;
|
||||
COMMIT;
|
||||
END snap_data_files;
|
||||
|
||||
PROCEDURE snap_free_space AS
|
||||
BEGIN
|
||||
INSERT INTO plancap$free_space
|
||||
SELECT
|
||||
sysdate
|
||||
, tablespace_name
|
||||
, file_id
|
||||
, SUM(bytes)
|
||||
, SUM(blocks)
|
||||
, relative_fno
|
||||
FROM
|
||||
dba_free_space
|
||||
GROUP BY
|
||||
sysdate, tablespace_name, file_id, relative_fno;
|
||||
COMMIT;
|
||||
END snap_free_space;
|
||||
|
||||
PROCEDURE snap_segment_space AS
|
||||
BEGIN
|
||||
INSERT INTO plancap$segment_space
|
||||
SELECT
|
||||
sysdate
|
||||
, owner
|
||||
, segment_name
|
||||
, NVL(partition_name,'-') partition_name
|
||||
, segment_type
|
||||
, tablespace_name
|
||||
, SUM(bytes) bytes
|
||||
, SUM(blocks) blocks
|
||||
, SUM(extents) extents
|
||||
FROM
|
||||
dba_segments
|
||||
GROUP BY
|
||||
sysdate, owner, segment_name, NVL(partition_name,'-'), tablespace_name, segment_type;
|
||||
COMMIT;
|
||||
END snap_segment_space;
|
||||
|
||||
|
||||
PROCEDURE snap_service_stats AS
|
||||
BEGIN
|
||||
INSERT INTO plancap$service_stats
|
||||
WITH sq AS (
|
||||
SELECT service_name,stat_name,value FROM v$service_stats
|
||||
)
|
||||
SELECT
|
||||
sysdate
|
||||
, a.service_name
|
||||
, a.value DB_CPU
|
||||
, b.value EXECUTE_COUNT
|
||||
, c.value USER_COMMITS
|
||||
, d.value USER_CALLS
|
||||
FROM
|
||||
sq a
|
||||
, sq b
|
||||
, sq c
|
||||
, sq d
|
||||
WHERE
|
||||
a.service_name = b.service_name
|
||||
AND b.service_name = c.service_name
|
||||
AND c.service_name = d.service_name
|
||||
AND a.stat_name = 'DB CPU'
|
||||
AND b.stat_name = 'execute count'
|
||||
AND c.stat_name = 'user commits'
|
||||
AND d.stat_name = 'user calls';
|
||||
COMMIT;
|
||||
END;
|
||||
|
||||
|
||||
END plancap_collector;
|
||||
/
|
||||
|
||||
SHOW ERR
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
67
tpt/tools/collectors/plancap_collector_schema.sql
Normal file
67
tpt/tools/collectors/plancap_collector_schema.sql
Normal file
@@ -0,0 +1,67 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- drop table plancap$data_files;
|
||||
-- drop table plancap$free_space;
|
||||
-- drop table plancap$segment_space;
|
||||
|
||||
CREATE TABLE plancap$data_files (
|
||||
snap_time DATE NOT NULL
|
||||
, tablespace_name VARCHAR2(100) NOT NULL
|
||||
, file_id NUMBER NOT NULL
|
||||
, bytes NUMBER NOT NULL
|
||||
, blocks NUMBER NOT NULL
|
||||
, relative_fno NUMBER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE plancap$data_files ADD CONSTRAINT pk_data_files
|
||||
PRIMARY KEY (snap_time,tablespace_name,file_id);
|
||||
|
||||
CREATE TABLE plancap$free_space (
|
||||
snap_time DATE NOT NULL
|
||||
, tablespace_name VARCHAR2(100) NOT NULL
|
||||
, file_id NUMBER NOT NULL
|
||||
, bytes NUMBER NOT NULL
|
||||
, blocks NUMBER NOT NULL
|
||||
, relative_fno NUMBER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE plancap$free_space ADD CONSTRAINT pk_free_space
|
||||
PRIMARY KEY (snap_time,tablespace_name,file_id);
|
||||
|
||||
|
||||
CREATE TABLE plancap$segment_space(
|
||||
snap_time DATE NOT NULL
|
||||
, owner VARCHAR2(100) NOT NULL
|
||||
, segment_name VARCHAR2(100) NOT NULL
|
||||
, partition_name VARCHAR2(100) NOT NULL
|
||||
, segment_type VARCHAR2(100) NOT NULL
|
||||
, tablespace_name VARCHAR2(100) NOT NULL
|
||||
, bytes NUMBER NOT NULL
|
||||
, blocks NUMBER NOT NULL
|
||||
, extents NUMBER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE plancap$segment_space ADD CONSTRAINT pk_segment_space
|
||||
PRIMARY KEY (snap_time,owner,segment_name,partition_name,segment_type);
|
||||
|
||||
CREATE TABLE plancap$service_stats (
|
||||
snap_time DATE NOT NULL
|
||||
, service_name VARCHAR2(100) NOT NULL
|
||||
, db_cpu NUMBER NOT NULL
|
||||
, execute_count NUMBER NOT NULL
|
||||
, user_commits NUMBER NOT NULL
|
||||
, user_calls NUMBER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE plancap$service_stats ADD CONSTRAINT pk_service_stats
|
||||
PRIMARY KEY (snap_time,service_name);
|
||||
|
||||
|
||||
CREATE PUBLIC SYNONYM plancap$data_files FOR plancap$data_files;
|
||||
CREATE PUBLIC SYNONYM plancap$free_space FOR plancap$free_space;
|
||||
CREATE PUBLIC SYNONYM plancap$segment_space FOR plancap$segment_space;
|
||||
|
||||
GRANT SELECT ON plancap$data_files to DBA;
|
||||
GRANT SELECT ON plancap$free_space to DBA;
|
||||
GRANT SELECT ON plancap$segment_space to DBA;
|
||||
@@ -0,0 +1,58 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- select * from v$shared_pool_reserved;
|
||||
--CREATE TABLE tanel_ksmspr TABLESPACE USERS AS SELECT * FROM sys.x$ksmspr;
|
||||
--CREATE TABLE tanel_kglob STORAGE (INITIAL 10M NEXT 10M PCTINCREASE 0) TABLESPACE users AS SELECT * FROM sys.x$kglob;
|
||||
|
||||
SELECT
|
||||
l.kglnaown owner
|
||||
, l.kglnaobj object_name
|
||||
, l.kglnahsh hash_value
|
||||
, decode(l.kglhdnsp,0,'CURSOR',1,'TABLE/PROCEDURE',2,'BODY',3,'TRIGGER', 4,'INDEX',5,'CLUSTER',6,'OBJECT',
|
||||
13,'JAVA SOURCE',14,'JAVA RESOURCE', 15,'REPLICATED TABLE OBJECT',
|
||||
16,'REPLICATION INTERNAL PACKAGE',
|
||||
17,'CONTEXT
|
||||
POLICY',18,'PUB_SUB',19,'SUMMARY',20,'DIMENSION', 21,'APP CONTEXT',22,'STORED OUTLINE'
|
||||
,23,'RULESET',24,'RSRC PLAN',
|
||||
25,'RSRC CONSUMER GROUP',26,'PENDING RSRC PLAN',27,'PENDING RSRC CONSUMER GROUP',
|
||||
28,'SUBSCRIPTION',29,'LOCATION',30,'REMOTE OBJECT',
|
||||
31,'SNAPSHOT METADATA',32,'JAVA SHARED DATA',33,'SECURITY PROFILE', 'INVALID NAMESPACE') obj_namespace
|
||||
, decode(bitand(l.kglobflg,3),0,'NOT LOADED',2,'NON-EXISTENT',3,'INVALID STATUS',
|
||||
decode(kglobtyp, 0,'CURSOR',1,'INDEX',2,'TABLE',3,'CLUSTER',4,'VIEW',
|
||||
5,'SYNONYM',6,'SEQUENCE',7,'PROCEDURE',8,'FUNCTION',9,'PACKAGE',10, 'NON-EXISTENT',
|
||||
11,'PACKAGE BODY',12,'TRIGGER',13,'TYPE',14,'TYPE BODY',
|
||||
15,'OBJECT',16,'USER',17,'DBLINK',18,'PIPE',19,'TABLE PARTITION'
|
||||
, 20,'INDEX PARTITION',21,'LOB',22,'LIBRARY',23,'DIRECTORY',24,'QUEUE',
|
||||
25,'INDEX-ORGANIZED TABLE',26,'REPLICATION OBJECT GROUP',
|
||||
27,'REPLICATION PROPAGATOR', 28,'JAVA SOURCE',29,'JAVA CLASS',30,'JAVA RESOURCE'
|
||||
,31,'JAVA JAR', 32,'INDEX TYPE',33,
|
||||
'OPERATOR',34,'TABLE SUBPARTITION',35,'INDEX SUBPARTITION',
|
||||
36, 'REPLICATED TABLE OBJECT',37,'REPLICATION INTERNAL PACKAGE', 38,'CONTEXT POLICY'
|
||||
,39,'PUB_SUB',40,'LOB PARTITION',41,'LOB SUBPARTITION', 42,'SUMMARY',43,'DIMENSION'
|
||||
,44,'APP CONTEXT',45,'STORED OUTLINE',46,'RULESET', 47,'RSRC PLAN',
|
||||
48,'RSRC CONSUMER GROUP',49,'PENDING RSRC PLAN', 50,'PENDING RSRC CONSUMER GROUP'
|
||||
,51,'SUBSCRIPTION',52,'LOCATION', 53,'REMOTE OBJECT',54,'SNAPSHOT METADATA',55,'IFS'
|
||||
, 56,'JAVA SHARED DATA',57,'SECURITY PROFILE','INVALID TYPE')) obj_type
|
||||
, s.ksmchptr
|
||||
, s.ksmchsiz
|
||||
, s.ksmchcls
|
||||
, s.ksmchcom
|
||||
, s.ksmchpar
|
||||
FROM
|
||||
tanel_ksmspr s
|
||||
, tanel_kglob l
|
||||
-- x$ksmspr s
|
||||
--, x$kglob l
|
||||
WHERE
|
||||
s.ksmchptr = l.kglobhd0
|
||||
OR s.ksmchptr = l.kglobhd1
|
||||
OR s.ksmchptr = l.kglobhd2
|
||||
OR s.ksmchptr = l.kglobhd3
|
||||
OR s.ksmchptr = l.kglobhd4
|
||||
OR s.ksmchptr = l.kglobhd5
|
||||
OR s.ksmchptr = l.kglobhd6
|
||||
OR s.ksmchptr = l.kglobhd7
|
||||
ORDER BY
|
||||
s.ksmchsiz
|
||||
/
|
||||
@@ -0,0 +1,204 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- monitor shared pool activity, free memory and chunk flushing
|
||||
--
|
||||
-- USAGE:
|
||||
-- exec shared_pool_monitor.get_all( <sampling_interval>, <how_many_samples )
|
||||
--
|
||||
-- exec shared_pool_monitor.get_all -- this will sample every 10 minutes, forever
|
||||
|
||||
|
||||
CREATE OR REPLACE PACKAGE shared_pool_monitor AS
|
||||
PROCEDURE get_subpool_stats (p_date IN DATE DEFAULT SYSDATE);
|
||||
PROCEDURE get_flush_stats (p_date IN DATE DEFAULT SYSDATE);
|
||||
PROCEDURE get_heap_activity_stats (p_date IN DATE DEFAULT SYSDATE);
|
||||
PROCEDURE get_reserved_chunk_stats (p_date IN DATE DEFAULT SYSDATE);
|
||||
PROCEDURE get_reserved_chunk_details (p_date IN DATE DEFAULT SYSDATE);
|
||||
PROCEDURE get_all (p_sleep IN NUMBER DEFAULT 600, p_times IN NUMBER DEFAULT 0);
|
||||
END shared_pool_monitor;
|
||||
/
|
||||
SHOW ERR
|
||||
|
||||
CREATE OR REPLACE PACKAGE BODY shared_pool_monitor AS
|
||||
|
||||
PROCEDURE get_subpool_stats(p_date IN DATE DEFAULT SYSDATE) AS
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_SUBPOOL_STATS:BEGIN');
|
||||
|
||||
INSERT INTO spmon_subpool_stats (sample_time,subpool,name,bytes)
|
||||
SELECT
|
||||
SYSDATE
|
||||
, ksmdsidx
|
||||
, ksmssnam
|
||||
, SUM(ksmsslen)
|
||||
FROM
|
||||
x$ksmss
|
||||
WHERE
|
||||
ksmsslen > 0
|
||||
AND ksmdsidx > 0
|
||||
GROUP BY
|
||||
SYSDATE
|
||||
, ksmdsidx
|
||||
, ksmssnam;
|
||||
|
||||
COMMIT;
|
||||
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_SUBPOOL_STATS:END');
|
||||
END get_subpool_stats;
|
||||
|
||||
PROCEDURE get_flush_stats(p_date IN DATE DEFAULT SYSDATE) AS
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_FLUSH_STATS:BEGIN');
|
||||
|
||||
-- this procedure relies on the fact that X$KSMLRU contents are cleared out
|
||||
-- automatically every time it's queried
|
||||
INSERT INTO spmon_flush_stats ( sample_time, addr, indx, inst_id, chunk_subpool
|
||||
, chunk_duration, chunk_comment , chunk_size
|
||||
, chunks_flushed_out , flusher_object_name
|
||||
, flusher_hash_value , flusher_ses_addr )
|
||||
SELECT
|
||||
p_date sample_time
|
||||
, ADDR
|
||||
, INDX
|
||||
, INST_ID
|
||||
, KSMLRIDX
|
||||
, KSMLRDUR
|
||||
, KSMLRCOM
|
||||
, KSMLRSIZ
|
||||
, KSMLRNUM
|
||||
, KSMLRHON
|
||||
, KSMLROHV
|
||||
, KSMLRSES
|
||||
FROM
|
||||
x$ksmlru
|
||||
WHERE
|
||||
ksmlrnum > 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_FLUSH_STATS:END');
|
||||
END get_flush_stats;
|
||||
|
||||
PROCEDURE get_heap_activity_stats(p_date IN DATE DEFAULT SYSDATE) AS
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_HEAP_ACTIVITY_STATS:BEGIN');
|
||||
|
||||
INSERT INTO spmon_heap_activity_stats
|
||||
SELECT
|
||||
p_date
|
||||
, kghluidx
|
||||
, kghludur
|
||||
, kghlufsh
|
||||
, kghluops
|
||||
, kghlurcr
|
||||
, kghlutrn
|
||||
, kghlunfu
|
||||
, kghlunfs
|
||||
, kghlumxa
|
||||
, kghlumes
|
||||
, kghlumer
|
||||
, kghlurcn
|
||||
, kghlurmi
|
||||
, kghlurmz
|
||||
, kghlurmx
|
||||
FROM
|
||||
x$kghlu;
|
||||
COMMIT;
|
||||
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_HEAP_ACTIVITY_STATS:END');
|
||||
END get_heap_activity_stats;
|
||||
|
||||
PROCEDURE get_reserved_chunk_details(p_date IN DATE DEFAULT SYSDATE) AS
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_RESERVED_CHUNKS:BEGIN');
|
||||
INSERT INTO spmon_reserved_chunk_details
|
||||
SELECT
|
||||
p_date
|
||||
, ADDR
|
||||
, INDX
|
||||
, INST_ID
|
||||
, KSMCHCOM
|
||||
, KSMCHPTR
|
||||
, KSMCHSIZ
|
||||
, KSMCHCLS
|
||||
, KSMCHTYP
|
||||
, KSMCHPAR
|
||||
FROM
|
||||
x$ksmspr -- important, this view must be x$ksmspR <-- (not the x$ksmsp which may hang your instance)
|
||||
;
|
||||
COMMIT;
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_RESERVED_CHUNKS:END');
|
||||
END get_reserved_chunk_details;
|
||||
|
||||
|
||||
PROCEDURE get_reserved_chunk_stats(p_date IN DATE DEFAULT SYSDATE) AS
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_RESERVED_CHUNKS:BEGIN');
|
||||
INSERT INTO spmon_reserved_chunk_stats
|
||||
SELECT
|
||||
p_date
|
||||
, KSMCHCLS
|
||||
, KSMCHCOM
|
||||
, KSMCHTYP
|
||||
, COUNT(*)
|
||||
, SUM(KSMCHSIZ)
|
||||
, AVG(KSMCHSIZ)
|
||||
, MIN(KSMCHSIZ)
|
||||
, MAX(KSMCHSIZ)
|
||||
FROM
|
||||
x$ksmspr -- important, this view must be x$ksmspR <-- (not the x$ksmsp which may hang your instance)
|
||||
GROUP BY
|
||||
p_date
|
||||
, ksmchcls
|
||||
, ksmchcom
|
||||
, ksmchtyp;
|
||||
|
||||
COMMIT;
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('GET_RESERVED_CHUNKS:END');
|
||||
END get_reserved_chunk_stats;
|
||||
|
||||
|
||||
|
||||
PROCEDURE get_all(p_sleep IN NUMBER DEFAULT 600, p_times IN NUMBER DEFAULT 0) AS
|
||||
cur_date DATE;
|
||||
BEGIN
|
||||
|
||||
IF p_times > 0 THEN -- sample x times
|
||||
FOR i IN 1..p_times LOOP
|
||||
cur_date := SYSDATE;
|
||||
|
||||
get_subpool_stats(cur_date);
|
||||
get_heap_activity_stats(cur_date);
|
||||
get_flush_stats(cur_date);
|
||||
get_reserved_chunk_stats(cur_date);
|
||||
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('MAIN LOOP:SLEEPING');
|
||||
DBMS_LOCK.SLEEP(p_sleep);
|
||||
END LOOP; -- 1..p_times
|
||||
ELSE -- sample forever
|
||||
WHILE TRUE LOOP
|
||||
cur_date := SYSDATE;
|
||||
|
||||
get_subpool_stats(cur_date);
|
||||
get_heap_activity_stats(cur_date);
|
||||
get_flush_stats(cur_date);
|
||||
get_reserved_chunk_stats(cur_date);
|
||||
|
||||
DBMS_APPLICATION_INFO.SET_ACTION('MAIN LOOP:SLEEPING');
|
||||
DBMS_LOCK.SLEEP(p_sleep);
|
||||
END LOOP; -- while true
|
||||
END IF; -- p_times > 0
|
||||
|
||||
END get_all;
|
||||
|
||||
BEGIN
|
||||
DBMS_APPLICATION_INFO.SET_MODULE('SHARED POOL MONITOR', 'PACKAGE INITIALIZATION');
|
||||
|
||||
END shared_pool_monitor;
|
||||
/
|
||||
|
||||
SHOW ERR
|
||||
|
||||
GRANT EXECUTE ON shared_pool_monitor TO perfstat;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT
|
||||
SAMPLE_TIME
|
||||
, SUBPOOL
|
||||
, DURATION
|
||||
, FLUSHED_CHUNKS_D
|
||||
, LRU_OPERATIONS_D
|
||||
, RESERVED_SCANS
|
||||
, RESERVED_MISSES
|
||||
, UNSUCCESSFUL_FLUSHES
|
||||
, LAST_UNSUCC_MISS_REQ_SIZE
|
||||
, LAST_UNSUCC_FLUSH_REQ_SIZE
|
||||
FROM
|
||||
sys.SPMON_HEAP_ACTIVITY_VIEW
|
||||
WHERE
|
||||
sample_time BETWEEN %FROM_DATE% AND %TO_DATE%
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- change to whichever tablespace you want to create these tables in
|
||||
DEF tablespace=TOOLS
|
||||
|
||||
-- x$ksmss (v$sgastat)
|
||||
CREATE TABLE spmon_subpool_stats (
|
||||
sample_time DATE
|
||||
, subpool NUMBER
|
||||
, name VARCHAR2(100)
|
||||
, bytes NUMBER
|
||||
)
|
||||
TABLESPACE &tablespace STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0);
|
||||
|
||||
-- x$ksmlru
|
||||
CREATE TABLE spmon_flush_stats (
|
||||
sample_time DATE
|
||||
, addr RAW(8)
|
||||
, indx NUMBER
|
||||
, inst_id NUMBER
|
||||
, chunk_subpool NUMBER
|
||||
, chunk_duration NUMBER
|
||||
, chunk_comment VARCHAR2(100)
|
||||
, chunk_size NUMBER
|
||||
, chunks_flushed_out NUMBER
|
||||
, flusher_object_name VARCHAR2(100)
|
||||
, flusher_hash_value NUMBER
|
||||
, flusher_ses_addr RAW(8)
|
||||
)
|
||||
TABLESPACE &tablespace STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0);
|
||||
|
||||
-- x$kghlu (part of v$shared_pool_reserved)
|
||||
CREATE TABLE spmon_heap_activity_stats (
|
||||
sample_time DATE
|
||||
, kghluidx NUMBER -- subpool id
|
||||
, kghludur NUMBER -- allocation duration class
|
||||
, kghlufsh NUMBER -- chunks flushed
|
||||
, kghluops NUMBER -- LRU operations (moving chunks around in LRU list)
|
||||
, kghlurcr NUMBER -- recurrent chunks (pinned/unpinned 3 times or more)
|
||||
, kghlutrn NUMBER -- transient chunks (pinned 1-2 times)
|
||||
, kghlumxa NUMBER --
|
||||
, kghlumes NUMBER --
|
||||
, kghlumer NUMBER --
|
||||
, kghlurcn NUMBER -- reserved freelist scans
|
||||
, kghlurmi NUMBER -- reserved freelist misses
|
||||
, kghlurmz NUMBER -- last reserved scan miss size
|
||||
, kghlurmx NUMBER -- reserved list scan max miss size
|
||||
, kghlunfu NUMBER -- number of free-unpinned unsuccessful attempts
|
||||
, kghlunfs NUMBER -- last free unpinned unsuccessful size
|
||||
)
|
||||
TABLESPACE &tablespace STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0);
|
||||
|
||||
CREATE OR REPLACE VIEW spmon_heap_activity_view AS
|
||||
SELECT
|
||||
sample_time
|
||||
, kghluidx subpool
|
||||
, kghludur duration
|
||||
, CASE WHEN kghlufsh - NVL(lag(kghlufsh,1) over (partition by kghluidx, kghludur order by sample_time), kghlufsh) < 0
|
||||
THEN kghlufsh
|
||||
ELSE kghlufsh - lag(kghlufsh,1) over (partition by kghluidx, kghludur order by sample_time)
|
||||
END flushed_chunks_d
|
||||
, CASE WHEN kghluops - NVL(lag(kghluops,1) over (partition by kghluidx, kghludur order by sample_time), kghluops) < 0
|
||||
THEN kghluops
|
||||
ELSE kghluops - lag(kghluops,1) over (partition by kghluidx, kghludur order by sample_time)
|
||||
END lru_operations_d
|
||||
, CASE WHEN kghlurcn - NVL(lag(kghlurcn,1) over (partition by kghluidx, kghludur order by sample_time), kghlurcn) < 0
|
||||
THEN kghlurcn
|
||||
ELSE kghlurcn - lag(kghlurcn,1) over (partition by kghluidx, kghludur order by sample_time)
|
||||
END reserved_scans
|
||||
, CASE WHEN kghlurmi - NVL(lag(kghlurmi,1) over (partition by kghluidx, kghludur order by sample_time), kghlurmi) < 0
|
||||
THEN kghlurmi
|
||||
ELSE kghlurmi - lag(kghlurmi,1) over (partition by kghluidx, kghludur order by sample_time)
|
||||
END reserved_misses
|
||||
, CASE WHEN kghlunfu - NVL(lag(kghlunfu,1) over (partition by kghluidx, kghludur order by sample_time), kghlunfu) < 0
|
||||
THEN kghlunfu
|
||||
ELSE kghlunfu - lag(kghlunfu,1) over (partition by kghluidx, kghludur order by sample_time)
|
||||
END unsuccessful_flushes
|
||||
, kghlurmz last_unsucc_miss_req_size
|
||||
, kghlunfs last_unsucc_flush_req_size
|
||||
FROM
|
||||
spmon_heap_activity_stats
|
||||
/
|
||||
|
||||
-- chunk details (all chunks in reserved area are dumped here)
|
||||
-- x$ksmspr (v$shared_pool_reserved)
|
||||
CREATE TABLE spmon_reserved_chunk_details (
|
||||
sample_time DATE
|
||||
, addr RAW(8)
|
||||
, indx NUMBER
|
||||
, inst_id NUMBER
|
||||
, ksmchcom VARCHAR2(100)
|
||||
, ksmchptr RAW(8)
|
||||
, ksmchsiz NUMBER
|
||||
, ksmchcls VARCHAR2(100)
|
||||
, ksmchtyp NUMBER
|
||||
, ksmchpar RAW(8)
|
||||
)
|
||||
TABLESPACE &tablespace STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0);
|
||||
|
||||
-- min,max,avg chunk size grouped by chunk type and (allocation reason) comment
|
||||
-- x$ksmspr (v$shared_pool_reserved) summary
|
||||
CREATE TABLE spmon_reserved_chunk_stats (
|
||||
sample_time DATE
|
||||
, ksmchcls VARCHAR2(100)
|
||||
, ksmchcom VARCHAR2(100)
|
||||
, ksmchtype NUMBER
|
||||
, chunk_count NUMBER
|
||||
, total_size NUMBER
|
||||
, avg_size NUMBER
|
||||
, min_size NUMBER
|
||||
, max_size NUMBER
|
||||
)
|
||||
TABLESPACE &tablespace STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0);
|
||||
|
||||
GRANT SELECT ON SPMON_FLUSH_STATS TO PERFSTAT;
|
||||
GRANT SELECT ON SPMON_HEAP_ACTIVITY_STATS TO PERFSTAT;
|
||||
GRANT SELECT ON SPMON_RESERVED_CHUNK_DETAILS TO PERFSTAT;
|
||||
GRANT SELECT ON SPMON_RESERVED_CHUNK_STATS TO PERFSTAT;
|
||||
GRANT SELECT ON SPMON_SUBPOOL_STATS TO PERFSTAT;
|
||||
|
||||
GRANT SELECT ON spmon_heap_activity_view TO PERFSTAT;
|
||||
|
||||
|
||||
13
tpt/tools/collectors/space_collect.sql
Normal file
13
tpt/tools/collectors/space_collect.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- this script requires PLANCAP_COLLECTOR package
|
||||
-- which is created using these scripts
|
||||
-- 1) plancap_collector_schema.sql
|
||||
-- 2) plancap_collector.sql
|
||||
|
||||
EXEC SNAP_DATA_FILES
|
||||
EXEC SNAP_FREE_SPACE
|
||||
EXEC SNAP_SEGMENT_SPACE
|
||||
EXEC SNAP_SERVICE_STATS
|
||||
|
||||
13
tpt/tools/helper_views/gen_rows_1000000000.sql
Normal file
13
tpt/tools/helper_views/gen_rows_1000000000.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
CREATE OR REPLACE VIEW gen_rows_1000000000 AS
|
||||
SELECT r FROM (
|
||||
SELECT ROWNUM r
|
||||
FROM
|
||||
(SELECT ROWNUM r FROM dual CONNECT BY ROWNUM <= 1000) a,
|
||||
(SELECT ROWNUM r FROM dual CONNECT BY ROWNUM <= 1000) b,
|
||||
(SELECT ROWNUM r FROM dual CONNECT BY ROWNUM <= 1000) c
|
||||
)
|
||||
/
|
||||
|
||||
220
tpt/tools/moats_v1.05/README.txt
Normal file
220
tpt/tools/moats_v1.05/README.txt
Normal file
@@ -0,0 +1,220 @@
|
||||
|
||||
Mother Of All Tuning Scripts (MOATS) README
|
||||
===========================================
|
||||
|
||||
Copyright Information
|
||||
=====================
|
||||
MOATS v1.04, September 2010
|
||||
(c) Adrian Billington www.oracle-developer.net
|
||||
(c) Tanel Poder www.e2sn.com
|
||||
|
||||
Contents
|
||||
========
|
||||
1.0 Introduction
|
||||
2.0 Supported Versions
|
||||
3.0 Installation & Removal
|
||||
3.1 Prerequisites
|
||||
3.1.1 System Privileges
|
||||
3.1.2 Object Privileges
|
||||
3.2 Installation
|
||||
3.3 Removal
|
||||
4.0 Usage
|
||||
4.1 SQL*Plus Setup
|
||||
4.1.1 Window Size
|
||||
4.1.2 SQL*Plus Settings
|
||||
4.2 MOATS TOP Usage
|
||||
4.2.1 Using MOATS.TOP directly
|
||||
4.2.2 Using the TOP view
|
||||
4.3 Other MOATS APIs
|
||||
5.0 Roadmap
|
||||
6.0 Disclaimer
|
||||
7.0 Acknowledgements
|
||||
|
||||
|
||||
1.0 Introduction
|
||||
================
|
||||
MOATS is a simple tuning tool that samples active sessions and reports top database activity in regular screen refreshes at specified intervals (similar to the TOP utility for UNIX). MOATS is designed to run in sqlplus only and has recommended display settings to enable screen refreshes.
|
||||
|
||||
Examples of how this application might be used:
|
||||
|
||||
-- To report top session and instance activity at 5 second intervals...
|
||||
-- --------------------------------------------------------------------
|
||||
|
||||
SQL> set arrays 36 lines 110 head off tab off
|
||||
|
||||
SQL> SELECT * FROM TABLE(moats.top(5));
|
||||
|
||||
|
||||
-- Sample output...
|
||||
-- --------------------------------------------------------------------
|
||||
|
||||
MOATS: The Mother Of All Tuning Scripts v1.0 by Adrian Billington & Tanel Poder
|
||||
http://www.oracle-developer.net & http://www.e2sn.com
|
||||
|
||||
+ INSTANCE SUMMARY ------------------------------------------------------------------------------------------+
|
||||
| Instance: ora112 | Execs/s: 2.0 | sParse/s: 0.0 | LIOs/s: 219637.3 | Read MB/s: 0.0 |
|
||||
| Cur Time: 13-Aug 19:25:14 | Calls/s: 0.0 | hParse/s: 0.0 | PhyRD/s: 0.5 | Write MB/s: 0.0 |
|
||||
| History: 0h 0m 26s | Commits/s: 0.0 | ccHits/s: 1.5 | PhyWR/s: 2.9 | Redo MB/s: 0.0 |
|
||||
+------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
+ TOP SQL_ID (child#) -----+ TOP SESSIONS ---------+ + TOP WAITS -------------------------+ WAIT CLASS -+
|
||||
| 50% | bwx4var9q4y9f (0) | 71 | | 100% | latch: cache buffers chains | Concurrency |
|
||||
| 50% | bq2qr0bhjyv1c (0) | 133 | | 50% | SQL*Net message to client | Network |
|
||||
| 50% | 799uuu8tpf6rk (0) | 6 | | | |
|
||||
+--------------------------------------------------+ +--------------------------------------------------+
|
||||
|
||||
+ TOP SQL_ID ----+ PLAN_HASH_VALUE + SQL TEXT ---------------------------------------------------------------+
|
||||
| bwx4var9q4y9f | 2119813036 | select /*+ full(a) full(b) use_nl(a b) */ count(*) from sys.obj$ a, |
|
||||
| | | ys.obj$ b where a.name = b.name and rownum <= 1000002 |
|
||||
+ ---------------------------------------------------------------------------------------------------------- +
|
||||
| bq2qr0bhjyv1c | 644658511 | select moats_ash_ot( systimestamp, saddr, sid, serial#, audsid, paddr, |
|
||||
| | | er#, username, command, ownerid, taddr |
|
||||
+ ---------------------------------------------------------------------------------------------------------- +
|
||||
| 799uuu8tpf6rk | 2119813036 | select /*+ full(a) full(b) use_nl(a b) */ count(*) from sys.obj$ a, |
|
||||
| | | ys.obj$ b where a.name = b.name and rownum <= 1000001 |
|
||||
+ ---------------------------------------------------------------------------------------------------------- +
|
||||
|
||||
|
||||
2.0 Supported Versions
|
||||
======================
|
||||
MOATS supports all Oracle versions of 10g Release 2 and above.
|
||||
|
||||
|
||||
3.0 Installation & Removal
|
||||
==========================
|
||||
MOATS requires several database objects to be created. The privileges, installation and removal steps are described below.
|
||||
|
||||
3.1 Prerequisites
|
||||
-----------------
|
||||
It is recommended that this application is installed in a "TOOLS" schema, but whichever schema is used requires the following privileges. Note that any or all of these grants can be assigned to either the MOATS target schema itself or a role that is granted to the MOATS target schema.
|
||||
|
||||
3.1.1 System Privileges
|
||||
-----------------------
|
||||
* CREATE TYPE
|
||||
* CREATE TABLE
|
||||
* CREATE VIEW
|
||||
* CREATE PROCEDURE
|
||||
|
||||
3.1.2 Object Privileges
|
||||
-----------------------
|
||||
* EXECUTE ON DBMS_LOCK
|
||||
* SELECT ON V_$SESSION ***
|
||||
* SELECT ON V_$STATNAME ***
|
||||
* SELECT ON V_$SYSSTAT ***
|
||||
* SELECT ON V_$LATCH ***
|
||||
* SELECT ON V_$TIMER ***
|
||||
* SELECT ON V_$SQL ***
|
||||
|
||||
*** Note:
|
||||
a) SELECT ANY DICTIONARY can be granted in place of the specific V$ view grants above
|
||||
b) Supplied scripts will grant/revoke all of the above to/from the MOATS target schema/role.
|
||||
|
||||
3.2 Installation
|
||||
----------------
|
||||
MOATS can be installed using sqlplus or any tools that fully support sqlplus commands. To install MOATS:
|
||||
|
||||
1) Ensure that the MOATS owner schema has the required privileges described in Section 3.1 above. A script named moats_privs_grant.sql is supplied if required (this will need to be run as a user with admin grant rights on SYS objects. This script will prompt for the name of the target MOATS schema).
|
||||
|
||||
2) To install MOATS, login as the target schema and run the moats_install.sql script. A warning will prompt for a continue/cancel option.
|
||||
|
||||
3.3 Removal
|
||||
-----------
|
||||
To remove MOATS, login as the MOATS owner schema and run the moats_remove.sql script. A warning will prompt for a continue/cancel option.
|
||||
|
||||
To revoke all related privileges from the MOATS owner schema, a script named moats_privs_revoke.sql is supplied if required (this will need to be run as a user with admin grant rights on SYS objects. This script will prompt for the name of the target MOATS schema).
|
||||
|
||||
4.0 Usage
|
||||
=========
|
||||
MOATS is simple to use. It is designed for sqlplus only and makes use of sqlplus and PL/SQL functionality to provide real-time screen refreshes. To make the most of MOATS v1.0, follow the steps below.
|
||||
|
||||
4.1 SQL*Plus Setup
|
||||
------------------
|
||||
MOATS TOP output is of a fixed size so needs some specific settings.
|
||||
|
||||
4.1.1 Setting Window Size
|
||||
-------------------------
|
||||
The MOATS.FORMAT_WINDOW procedure is a visual aid to setting the right screen size for MOATS. To run it, login to sqlplus and do the following:
|
||||
|
||||
* set serveroutput on format wrapped
|
||||
* exec moats.format_window
|
||||
* resize window to the dotted lines at the top and bottom of the FORMAT_WINDOW output
|
||||
|
||||
Window size should be at least 110 x 36 but the FORMAT_WINDOW procedure is the best way to get accurate and optimal settings for MOATS.
|
||||
|
||||
4.1.2 SQL*Plus Settings
|
||||
-----------------------
|
||||
MOATS comes with a moats_settings.sql file that does the following:
|
||||
|
||||
* set arrays 36
|
||||
* set lines 110
|
||||
* set head off
|
||||
* set tab off
|
||||
* set serveroutput on format wrapped
|
||||
|
||||
These are optimal sqlplus settings for the MOATS TOP utility and need to be set before running it (see Usage below).
|
||||
|
||||
4.2 MOATS TOP Usage
|
||||
-------------------
|
||||
MOATS.TOP is a pipelined function that outputs instance performance statistics at a given refresh interval. Before running TOP, the moats_settings.sql script (or equivalent) should be run in the sqlplus session. The following example refreshes the instance statistics at the default 10 seconds:
|
||||
|
||||
4.2.1 Using MOATS.TOP directly
|
||||
------------------------------
|
||||
|
||||
+-------------------------------------+
|
||||
| SQL> @moats_settings.sql |
|
||||
| |
|
||||
| SQL> SELECT * |
|
||||
| 2 FROM TABLE(moats.top); |
|
||||
+-------------------------------------+
|
||||
|
||||
To use a non-default refresh rate, supply it as follows:
|
||||
|
||||
+-------------------------------------+
|
||||
| SQL> SELECT * |
|
||||
| 2 FROM TABLE(moats.top(5)); |
|
||||
+-------------------------------------+
|
||||
|
||||
This example uses a 5 second refresh rate.
|
||||
|
||||
To stop MOATS.TOP refreshes, use a Ctrl-C interrupt.
|
||||
|
||||
4.2.2 Using the TOP view
|
||||
------------------------
|
||||
A view named TOP is included with MOATS for convenience.
|
||||
|
||||
+-------------------------------------+
|
||||
| SQL> @moats_settings.sql |
|
||||
| |
|
||||
| SQL> SELECT * FROM top; |
|
||||
+-------------------------------------+
|
||||
|
||||
To set a non-default value for refresh rate, set the MOATS refresh rate parameter, as follows.
|
||||
|
||||
+--------------------------------------------------------------+
|
||||
| SQL> @moats_settings.sql |
|
||||
| |
|
||||
| SQL> exec moats.set_parameter(moats.gc_top_refresh_rate, 3); |
|
||||
| |
|
||||
| SQL> SELECT * FROM top; |
|
||||
+--------------------------------------------------------------+
|
||||
|
||||
This example uses a 3 second refresh rate.
|
||||
|
||||
4.3 Other MOATS APIs
|
||||
--------------------
|
||||
MOATS contains several other public APIs that are currently for internal use only. These will be fully described and "released" with future MOATS versions but are currently only supported for use by MOATS.TOP. They include pipelined functions to query the active session data that MOATS gathers.
|
||||
|
||||
5.0 Roadmap
|
||||
===========
|
||||
There is no fixed roadmap at the time of writing. Features that Tanel and Adrian would like to add (but are not limited to) the following:
|
||||
|
||||
* formally expose the active session query functions for custom-reporting
|
||||
* add drill-down functionality for SQL statements of interest in the TOP output
|
||||
|
||||
6.0 Disclaimer
|
||||
==============
|
||||
This software is supplied in good faith and is free for download, but any subsequent use is entirely at the end-users' risk. Adrian Billington/oracle-developer.net and Tanel Poder/www.e2sn.com do not accept any responsibility for problems arising as a result of using MOATS. All users are strongly advised to read the installation and removal scripts prior to running them and test the application in an appropriate environment.
|
||||
|
||||
7.0 Acknowledgements
|
||||
====================
|
||||
Many thanks to Randolf Geist for his contributions to the latest version of MOATS, including several bug-fixes to the original alpha version.
|
||||
25
tpt/tools/moats_v1.05/global_test.sql
Normal file
25
tpt/tools/moats_v1.05/global_test.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- hack but ain't working
|
||||
|
||||
CREATE OR REPLACE FUNCTION f
|
||||
RETURN sys.dbms_debug_vc2coll PIPELINED
|
||||
AS
|
||||
BEGIN
|
||||
FOR i IN 1..3 LOOP
|
||||
FOR r IN (
|
||||
--SELECT USERENV('Instance')||','||TO_CHAR(sid)||','||TO_CHAR(serial#)||','||sql_id||','||state||','||event val
|
||||
--FROM v$session
|
||||
--WHERE status = 'ACTIVE' AND type = 'USER'
|
||||
WITH sq AS (SELECT /*+ NO_MERGE MATERIALIZE */ * FROM v$instance) SELECT TO_CHAR(instance_number)||' '||host_name val FROM sq
|
||||
) LOOP
|
||||
PIPE ROW (r.val);
|
||||
END LOOP;
|
||||
DBMS_LOCK.SLEEP(1);
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
|
||||
SHOW ERR;
|
||||
|
||||
890
tpt/tools/moats_v1.05/moats.pkb
Normal file
890
tpt/tools/moats_v1.05/moats.pkb
Normal file
@@ -0,0 +1,890 @@
|
||||
create or replace package body moats as
|
||||
|
||||
-- Internal types and global arrays for caching collections of
|
||||
-- SYSSTAT/ASH data for querying within MOATS...
|
||||
-- ------------------------------------------------------------------
|
||||
type moats_stat_ntt_aat is table of moats_stat_ntt
|
||||
index by pls_integer;
|
||||
g_stats moats_stat_ntt_aat;
|
||||
|
||||
type moats_ash_ntt_aat is table of moats_ash_ntt
|
||||
index by pls_integer;
|
||||
g_ash moats_ash_ntt_aat;
|
||||
|
||||
-- Internal type and variable for storing simple MOATS parameters...
|
||||
-- -----------------------------------------------------------------
|
||||
type parameter_aat is table of integer
|
||||
index by pls_integer;
|
||||
g_params parameter_aat;
|
||||
|
||||
-- Variables for maintaining ASH/SYSSTAT collections...
|
||||
-- ----------------------------------------------------
|
||||
g_ash_size pls_integer := 0;
|
||||
g_stat_size pls_integer := 0;
|
||||
|
||||
-- General constants...
|
||||
-- --------------------
|
||||
gc_space constant moats_output_ot := moats_output_ot(null);
|
||||
gc_mb constant pls_integer := 1048576;
|
||||
gc_gb constant pls_integer := 1048576*1024;
|
||||
gc_screen_size constant pls_integer := 36;
|
||||
gc_newline constant varchar2(1) := chr(10);
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure p( p_str in varchar2 ) is
|
||||
begin
|
||||
dbms_output.put_line(p_str);
|
||||
end p;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure po( p_str in moats_output_ot ) is
|
||||
begin
|
||||
p(p_str.output);
|
||||
end po;
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- procedure dump_ash is
|
||||
-- pragma autonomous_transaction;
|
||||
-- begin
|
||||
-- insert into moats_ash_dump select * from table(moats.get_ash);
|
||||
-- commit;
|
||||
-- end dump_ash;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure show_snaps is
|
||||
v_indx pls_integer;
|
||||
begin
|
||||
p('ASH snaps...');
|
||||
p('------------------------------------');
|
||||
v_indx := g_ash.first;
|
||||
while v_indx is not null loop
|
||||
p(utl_lms.format_message('Index=[%d] Count=[%d]', v_indx, g_ash(v_indx).count));
|
||||
v_indx := g_ash.next(v_indx);
|
||||
end loop;
|
||||
p('STAT snaps...');
|
||||
p('------------------------------------');
|
||||
v_indx := g_stats.first;
|
||||
while v_indx is not null loop
|
||||
p(utl_lms.format_message('Index=[%d] Count=[%d]', v_indx, g_stats(v_indx).count));
|
||||
v_indx := g_stats.next(v_indx);
|
||||
end loop;
|
||||
end show_snaps;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function banner return moats_output_ntt is
|
||||
begin
|
||||
return moats_output_ntt(
|
||||
moats_output_ot('MOATS: The Mother Of All Tuning Scripts v1.0 by Adrian Billington & Tanel Poder'),
|
||||
moats_output_ot(' http://www.oracle-developer.net & http://www.e2sn.com')
|
||||
);
|
||||
end banner;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function to_string ( p_collection in moats_v2_ntt,
|
||||
p_delimiter in varchar2 default ',',
|
||||
p_elements in pls_integer default null ) return varchar2 is
|
||||
v_str varchar2(4000);
|
||||
begin
|
||||
for i in 1 .. least(nvl(p_elements, p_collection.count), p_collection.count) loop
|
||||
v_str := v_str || p_delimiter || p_collection(i);
|
||||
end loop;
|
||||
return ltrim(v_str, p_delimiter);
|
||||
end to_string;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure format_window is
|
||||
v_banner moats_output_ntt := banner();
|
||||
c_boundary varchar2(110) := rpad('-',110,'-');
|
||||
procedure spaces( p_spaces in pls_integer ) is
|
||||
begin
|
||||
for i in 1 .. p_spaces loop
|
||||
po(gc_space);
|
||||
end loop;
|
||||
end spaces;
|
||||
begin
|
||||
p(c_boundary);
|
||||
spaces(2);
|
||||
for i in 1 .. v_banner.count loop
|
||||
p(v_banner(i).output);
|
||||
end loop;
|
||||
spaces(3);
|
||||
p(' MOATS.FORMAT_WINDOW');
|
||||
p(' -------------------');
|
||||
p(' Align sqlplus window size to dotted lines for optimal output');
|
||||
spaces(gc_screen_size-10);
|
||||
p(c_boundary);
|
||||
end format_window;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure set_parameter( p_parameter_code in pls_integer,
|
||||
p_parameter_value in integer ) is
|
||||
begin
|
||||
g_params(p_parameter_code) := p_parameter_value;
|
||||
end set_parameter;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function get_parameter ( p_parameter_code in pls_integer ) return integer is
|
||||
begin
|
||||
return g_params(p_parameter_code);
|
||||
end get_parameter;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure restore_default_parameters is
|
||||
begin
|
||||
set_parameter(moats.gc_ash_polling_rate, 1);
|
||||
set_parameter(moats.gc_ash_threshold, 1000);
|
||||
set_parameter(moats.gc_top_refresh_rate, 10);
|
||||
-- By default don't use a trailing ASH window
|
||||
set_parameter(moats.gc_ash_window_size, NULL);
|
||||
end restore_default_parameters;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function get_sql( p_select in varchar2,
|
||||
p_from in varchar2,
|
||||
p_where in varchar2,
|
||||
p_group_by in varchar2,
|
||||
p_order_by in varchar2 ) return varchar2 is
|
||||
v_sql varchar2(32767);
|
||||
begin
|
||||
v_sql := 'select ' || nvl(p_select, '*') || ' from ' || p_from;
|
||||
if p_where is not null then
|
||||
v_sql := v_sql || ' where ' || p_where;
|
||||
end if;
|
||||
if p_group_by is not null then
|
||||
v_sql := v_sql || ' group by ' || p_group_by;
|
||||
end if;
|
||||
if p_order_by is not null then
|
||||
v_sql := v_sql || ' order by ' || p_order_by;
|
||||
end if;
|
||||
return v_sql;
|
||||
end get_sql;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function ash_history return interval day to second is
|
||||
begin
|
||||
return g_ash(g_ash.last)(1).snaptime - g_ash(g_ash.first)(1).snaptime;
|
||||
end ash_history;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function ash_sample_count( p_lower_snap in pls_integer,
|
||||
p_upper_snap in pls_integer ) return pls_integer is
|
||||
v_samples pls_integer := 0;
|
||||
v_snap pls_integer;
|
||||
v_exit boolean := false;
|
||||
begin
|
||||
v_snap := p_lower_snap;
|
||||
while v_snap is not null and not v_exit loop
|
||||
-- Ignore dummy record
|
||||
if not (g_ash(v_snap).count = 1 and g_ash(v_snap)(1).sid is null) then
|
||||
v_samples := v_samples + g_ash(v_snap).count;
|
||||
end if;
|
||||
v_exit := (v_snap = p_upper_snap);
|
||||
v_snap := g_ash.next(v_snap);
|
||||
end loop;
|
||||
return greatest(v_samples,1);
|
||||
end ash_sample_count;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure maintain_ash_collection( p_index in pls_integer ) is
|
||||
begin
|
||||
if g_ash(p_index).count = 0 then
|
||||
g_ash.delete(p_index);
|
||||
else
|
||||
g_ash_size := g_ash_size + g_ash(p_index).count;
|
||||
while g_ash_size > g_params(moats.gc_ash_threshold) loop
|
||||
g_ash_size := g_ash_size - g_ash(g_ash.first).count;
|
||||
g_ash.delete(g_ash.first);
|
||||
end loop;
|
||||
end if;
|
||||
end maintain_ash_collection;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure snap_ash( p_index in pls_integer ) is
|
||||
v_sql_template varchar2(32767);
|
||||
v_sql varchar2(32767);
|
||||
begin
|
||||
|
||||
-- TODO: conditional compilation to get correct column list for version or
|
||||
-- select a small bunch of useful columns
|
||||
|
||||
-- Use dynamic SQL to avoid explicit grants on V$SESSION. Prepare the start
|
||||
-- of the SQL as it will be used twice...
|
||||
-- ------------------------------------------------------------------------
|
||||
v_sql_template := q'[select moats_ash_ot(
|
||||
systimestamp, saddr, %sid%, serial#, audsid, paddr, user#,
|
||||
username, command, ownerid, taddr, lockwait,
|
||||
status, server, schema#, schemaname, osuser,
|
||||
process, machine, terminal, program, type,
|
||||
sql_address, sql_hash_value, sql_id, sql_child_number,
|
||||
prev_sql_addr, prev_hash_value, prev_sql_id,
|
||||
prev_child_number, module, module_hash, action,
|
||||
action_hash, client_info, fixed_table_sequence,
|
||||
row_wait_obj#, row_wait_file#, row_wait_block#,
|
||||
row_wait_row#, logon_time, last_call_et, pdml_enabled,
|
||||
failover_type, failover_method, failed_over,
|
||||
resource_consumer_group, pdml_status, pddl_status,
|
||||
pq_status, current_queue_duration, client_identifier,
|
||||
blocking_session_status, blocking_instance,
|
||||
blocking_session, seq#, event#, case when state = 'WAITING' then event else 'ON CPU' end, p1text, p1,
|
||||
p1raw, p2text, p2, p2raw, p3text, p3, p3raw,
|
||||
wait_class_id, wait_class#, case when state = 'WAITING' then wait_class else 'ON CPU' end, wait_time,
|
||||
seconds_in_wait, state, service_name, sql_trace,
|
||||
sql_trace_waits, sql_trace_binds
|
||||
)
|
||||
from v$session
|
||||
where %preds%]';
|
||||
|
||||
v_sql := replace( v_sql_template, '%sid%', 'sid');
|
||||
v_sql := replace( v_sql, '%preds%', q'[ status = 'ACTIVE'
|
||||
and (wait_class != 'Idle' or state != 'WAITING')
|
||||
and sid != sys_context('userenv', 'sid')]' );
|
||||
|
||||
execute immediate v_sql bulk collect into g_ash(p_index);
|
||||
|
||||
-- If we have nothing to snap, add a dummy record that will be ignored
|
||||
-- in GET_ASH and GET_ASH_SAMPLE_COUNT...
|
||||
-- -------------------------------------------------------------------
|
||||
if g_ash(p_index).count = 0 then
|
||||
v_sql := replace( v_sql_template, '%sid%', 'null');
|
||||
v_sql := replace( v_sql, '%preds%', q'[sid = sys_context('userenv', 'sid')]' );
|
||||
execute immediate v_sql bulk collect into g_ash(p_index);
|
||||
end if;
|
||||
|
||||
maintain_ash_collection(p_index);
|
||||
|
||||
end snap_ash;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure reset_stats_collection is
|
||||
begin
|
||||
g_stats.delete;
|
||||
end reset_stats_collection;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure snap_stats( p_index in pls_integer,
|
||||
p_reset in boolean default false ) is
|
||||
begin
|
||||
|
||||
if p_reset then
|
||||
reset_stats_collection();
|
||||
end if;
|
||||
|
||||
-- Use dynamic SQL to avoid explicit grants on V$ views...
|
||||
-- -------------------------------------------------------
|
||||
execute immediate
|
||||
q'[select moats_stat_ot(type, name, value)
|
||||
from (
|
||||
select 'STAT' as type
|
||||
, sn.name
|
||||
, ss.value
|
||||
from v$statname sn
|
||||
, v$sysstat ss
|
||||
where sn.statistic# = ss.statistic#
|
||||
union all
|
||||
select 'LATCH'
|
||||
, name
|
||||
, gets
|
||||
from v$latch
|
||||
union all
|
||||
select 'TIMER'
|
||||
, 'moats timer'
|
||||
, hsecs
|
||||
from v$timer
|
||||
)]'
|
||||
bulk collect into g_stats(p_index);
|
||||
|
||||
end snap_stats;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function instance_summary ( p_lower_snap in pls_integer,
|
||||
p_upper_snap in pls_integer ) return moats_output_ntt is
|
||||
|
||||
type metric_aat is table of number
|
||||
index by pls_integer;
|
||||
v_rows moats_output_ntt := moats_output_ntt();
|
||||
v_metrics metric_aat;
|
||||
v_secs number; --<-- seconds between 2 stats snaps
|
||||
v_hivl interval day to second; --<-- interval of ASH history saved
|
||||
v_hstr varchar2(30); --<-- formatted hh:mi:ss string of history
|
||||
|
||||
begin
|
||||
|
||||
-- Get long and short metrics for range of stats. Order for fixed array offset...
|
||||
-- ------------------------------------------------------------------------------
|
||||
select upr.value - lwr.value
|
||||
bulk collect into v_metrics
|
||||
from table(g_stats(p_lower_snap)) lwr
|
||||
, table(g_stats(p_upper_snap)) upr
|
||||
where lwr.name = upr.name
|
||||
and lwr.name in ('execute count', 'parse count (hard)', 'parse count (total)',
|
||||
'physical read total IO requests', 'physical read total bytes',
|
||||
'physical write total IO requests', 'physical write total bytes',
|
||||
'redo size', 'redo writes', 'session cursor cache hits',
|
||||
'session logical reads', 'user calls', 'user commits',
|
||||
'moats timer')
|
||||
order by
|
||||
lwr.name;
|
||||
|
||||
-- 1 execute count
|
||||
-- 2 moats timer
|
||||
-- 3 parse count (hard)
|
||||
-- 4 parse count (total)
|
||||
-- 5 physical read total IO requests
|
||||
-- 6 physical read total bytes
|
||||
-- 7 physical write total IO requests
|
||||
-- 8 physical write total bytes
|
||||
-- 9 redo size
|
||||
-- 10 redo writes
|
||||
-- 11 session cursor cache hits
|
||||
-- 12 session logical reads
|
||||
-- 13 user calls
|
||||
-- 14 user commits
|
||||
|
||||
-- Execs/s: execute count
|
||||
-- sParse/s: parse count (total)
|
||||
-- LIOs/s: session logical reads
|
||||
-- Read MB/s: physical read total bytes / 1048576
|
||||
-- Calls/s: user calls
|
||||
-- hParse/s: parse count (hard)
|
||||
-- PhyRD/s: physical read total IO requests
|
||||
-- PhyWR/s: physical write total IO requests
|
||||
-- Write MB/s: physical write total bytes / 1048576
|
||||
-- History:
|
||||
-- Commits/s: user commits
|
||||
-- ccHits/s: session cursor cache hits
|
||||
-- Redo MB/s: redo size
|
||||
|
||||
-- Calculate number of seconds...
|
||||
-- ------------------------------
|
||||
v_secs := v_metrics(2)/100;
|
||||
|
||||
-- Calculate ASH history...
|
||||
-- ------------------------
|
||||
v_hivl := ash_history();
|
||||
v_hstr := to_char(extract(hour from v_hivl)) || 'h ' ||
|
||||
to_char(extract(minute from v_hivl)) || 'm ' ||
|
||||
to_char(trunc(extract(second from v_hivl))) || 's';
|
||||
|
||||
-- Set the instance summary output...
|
||||
-- ----------------------------------
|
||||
v_rows.extend(5);
|
||||
v_rows(1) := moats_output_ot(rpad('+ INSTANCE SUMMARY ',109,'-') || '+');
|
||||
v_rows(2) := moats_output_ot(
|
||||
rpad('| Instance: ' || sys_context('userenv','instance_name'), 28) ||
|
||||
' | Execs/s: ' || lpad(to_char(v_metrics(1)/v_secs, 'fm99990.0'), 7) ||
|
||||
' | sParse/s: ' || lpad(to_char((v_metrics(4)-v_metrics(3))/v_secs, 'fm99990.0'), 7) ||
|
||||
' | LIOs/s: ' || lpad(to_char(v_metrics(12)/v_secs, 'fm9999990.0'), 9) ||
|
||||
' | Read MB/s: ' || lpad(to_char(v_metrics(6)/v_secs/gc_mb, 'fm99990.0'), 7) ||
|
||||
' |');
|
||||
v_rows(3) := moats_output_ot(
|
||||
rpad('| Cur Time: ' || to_char(sysdate, 'DD-Mon hh24:mi:ss'), 28) ||
|
||||
' | Calls/s: ' || lpad(to_char(v_metrics(13)/v_secs, 'fm99990.0'), 7) ||
|
||||
' | hParse/s: ' || lpad(to_char(v_metrics(3)/v_secs, 'fm99990.0'), 7) ||
|
||||
' | PhyRD/s: ' || lpad(to_char(v_metrics(5)/v_secs, 'fm999990.0'), 8) ||
|
||||
' | Write MB/s: ' || lpad(to_char(v_metrics(8)/v_secs/gc_mb, 'fm9990.0'), 6) ||
|
||||
' |');
|
||||
v_rows(4) := moats_output_ot(
|
||||
rpad('| History: ' || v_hstr, 28) ||
|
||||
' | Commit/s: ' || lpad(to_char(v_metrics(14)/v_secs, 'fm99990'), 6) ||
|
||||
' | ccHits/s: ' || lpad(to_char(v_metrics(11)/v_secs, 'fm99990.0'), 7) ||
|
||||
' | PhyWR/s: ' || lpad(to_char(v_metrics(7)/v_secs, 'fm999990.0'), 8) ||
|
||||
' | Redo MB/s: ' || lpad(to_char(v_metrics(9)/v_secs/gc_mb, 'fm99990.0'), 7) ||
|
||||
' |');
|
||||
v_rows(5) := moats_output_ot(rpad('+-',109,'-') || '+');
|
||||
|
||||
return v_rows;
|
||||
|
||||
end instance_summary;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function top_summary ( p_lower_snap in pls_integer,
|
||||
p_upper_snap in pls_integer ) return moats_output_ntt is
|
||||
|
||||
type top_sql_rt is record
|
||||
( sql_id varchar2(64)
|
||||
, sql_child_number number
|
||||
, occurrences number
|
||||
, top_sids moats_v2_ntt );
|
||||
|
||||
type top_waits_rt is record
|
||||
( wait_name varchar2(64)
|
||||
, wait_class varchar2(64)
|
||||
, occurrences number );
|
||||
|
||||
type top_sql_aat is table of top_sql_rt
|
||||
index by pls_integer;
|
||||
|
||||
type top_waits_aat is table of top_waits_rt
|
||||
index by pls_integer;
|
||||
|
||||
v_row varchar2(4000);
|
||||
v_rows moats_output_ntt := moats_output_ntt();
|
||||
v_top_sqls top_sql_aat;
|
||||
v_top_waits top_waits_aat;
|
||||
v_samples pls_integer;
|
||||
|
||||
begin
|
||||
|
||||
-- Calculate number of ASH samples for this output...
|
||||
-- --------------------------------------------------
|
||||
v_samples := ash_sample_count( p_lower_snap => p_lower_snap,
|
||||
p_upper_snap => p_upper_snap );
|
||||
|
||||
-- Begin TOP summary...
|
||||
-- --------------------
|
||||
v_rows.extend;
|
||||
v_rows(1) := moats_output_ot(
|
||||
rpad('+ TOP SQL_ID (child#) ',27,'-') ||
|
||||
rpad('+ TOP SESSIONS ',24,'-') ||
|
||||
rpad('+',7) ||
|
||||
rpad('+ TOP WAITS ',37,'-') || '+ WAIT CLASS -+'
|
||||
);
|
||||
|
||||
-- Top SQL_IDs...
|
||||
-- --------------
|
||||
with ash_data as (
|
||||
select sid, sql_id, sql_child_number
|
||||
from table(
|
||||
moats.get_ash(
|
||||
p_lower_snap, p_upper_snap, moats.gc_all_rows))
|
||||
)
|
||||
select o_ash.sql_id
|
||||
, o_ash.sql_child_number
|
||||
, o_ash.occurrences
|
||||
, cast(
|
||||
multiset(
|
||||
select i_ash.sid
|
||||
from ash_data i_ash
|
||||
where i_ash.sql_id = o_ash.sql_id
|
||||
and i_ash.sql_child_number = o_ash.sql_child_number
|
||||
group by
|
||||
i_ash.sid
|
||||
order by
|
||||
count(*) desc
|
||||
) as moats_v2_ntt) as top_sids
|
||||
bulk collect into v_top_sqls
|
||||
from (
|
||||
select sql_id
|
||||
, sql_child_number
|
||||
, count(*) as occurrences
|
||||
from ash_data
|
||||
group by
|
||||
sql_id
|
||||
, sql_child_number
|
||||
order by
|
||||
count(*) desc
|
||||
) o_ash
|
||||
where rownum <= 5;
|
||||
|
||||
-- Top waits...
|
||||
-- ------------
|
||||
select substr(event,1,48)
|
||||
, wait_class
|
||||
, occurrences
|
||||
bulk collect into v_top_waits
|
||||
from (
|
||||
select event
|
||||
, wait_class
|
||||
, count(*) as occurrences
|
||||
from table(
|
||||
moats.get_ash(
|
||||
p_lower_snap, p_upper_snap, moats.gc_all_rows))
|
||||
group by
|
||||
event
|
||||
, wait_class
|
||||
order by
|
||||
count(*) desc
|
||||
)
|
||||
where rownum <= 5;
|
||||
|
||||
-- Summary output...
|
||||
-- -----------------
|
||||
for i in 1 .. greatest(v_top_sqls.count, v_top_waits.count) loop
|
||||
v_rows.extend;
|
||||
v_row := case
|
||||
when v_top_sqls.exists(i)
|
||||
then '|' || lpad(to_char((v_top_sqls(i).occurrences/v_samples)*100, 'fm9999'),4) || '% ' ||
|
||||
rpad('| ' || v_top_sqls(i).sql_id || ' (' || v_top_sqls(i).sql_child_number || ')', 20) ||
|
||||
rpad('| ' || to_string(v_top_sqls(i).top_sids, p_elements => 5), 23) ||
|
||||
rpad(' |', 8)
|
||||
else rpad('|', 7) ||
|
||||
rpad('| ', 20) ||
|
||||
rpad('| ', 23) ||
|
||||
rpad(' |', 8)
|
||||
end;
|
||||
v_row := v_row ||
|
||||
case
|
||||
when v_top_waits.exists(i)
|
||||
then '|' || lpad(to_char((v_top_waits(i).occurrences/v_samples)*100, 'fm9999'),4) || '% ' ||
|
||||
rpad('| ' || substr(v_top_waits(i).wait_name,1,35), 29) ||
|
||||
rpad(' | ' || v_top_waits(i).wait_class, 15) || '|'
|
||||
else rpad('|', 7) ||
|
||||
rpad('| ', 29) ||
|
||||
rpad(' | ', 15) ||
|
||||
'|'
|
||||
end;
|
||||
|
||||
v_rows(v_rows.last) := moats_output_ot(v_row);
|
||||
end loop;
|
||||
|
||||
v_rows.extend(2);
|
||||
v_rows(v_rows.last-1) := moats_output_ot(
|
||||
rpad('+',51,'-') || rpad('+',7) || rpad('+',51,'-') || '+'
|
||||
);
|
||||
v_rows(v_rows.last) := gc_space;
|
||||
|
||||
-- Top SQL output - we're going to deliberately loop r-b-r for the sql_ids...
|
||||
-- --------------------------------------------------------------------------
|
||||
v_rows.extend;
|
||||
v_rows(v_rows.last) := moats_output_ot(
|
||||
rpad('+ TOP SQL_ID ----+ PLAN_HASH_VALUE + SQL TEXT ', 109, '-') || '+'
|
||||
);
|
||||
for i in 1 .. v_top_sqls.count loop
|
||||
for r_sql in (select sql_id, child_number, sql_text, plan_hash_value
|
||||
from v$sql
|
||||
where sql_id = v_top_sqls(i).sql_id
|
||||
and child_number = v_top_sqls(i).sql_child_number)
|
||||
loop
|
||||
v_rows.extend;
|
||||
v_rows(v_rows.last) := moats_output_ot(
|
||||
rpad('| ' || r_sql.sql_id, 17) ||
|
||||
rpad('| ' || r_sql.plan_hash_value, 18) ||
|
||||
rpad('| ' || substr(r_sql.sql_text, 1, 71), 73) || ' |'
|
||||
);
|
||||
if length(r_sql.sql_text) > 74 then
|
||||
v_rows.extend;
|
||||
v_rows(v_rows.last) := moats_output_ot(
|
||||
rpad('| ', 17) ||
|
||||
rpad('| ', 18) ||
|
||||
rpad('| ' || substr(r_sql.sql_text, 72, 71), 73) || ' |'
|
||||
);
|
||||
end if;
|
||||
v_rows.extend;
|
||||
v_rows(v_rows.last) := moats_output_ot(
|
||||
rpad('+ ', 17, '-') ||
|
||||
rpad('-', 18, '-') ||
|
||||
rpad('-', 73, '-') || ' +'
|
||||
);
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
return v_rows;
|
||||
|
||||
end top_summary;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
procedure poll( p_refresh_rate in integer,
|
||||
p_include_ash in boolean,
|
||||
p_include_stat in boolean,
|
||||
p_lower_snap out pls_integer,
|
||||
p_upper_snap out pls_integer ) is
|
||||
|
||||
v_index pls_integer;
|
||||
v_refresh_rate integer := nvl(p_refresh_rate, g_params(moats.gc_top_refresh_rate));
|
||||
|
||||
function snap_index return pls_integer is
|
||||
begin
|
||||
return dbms_utility.get_time();
|
||||
end snap_index;
|
||||
|
||||
begin
|
||||
|
||||
-- Set starting snap index...
|
||||
-- --------------------------
|
||||
v_index := snap_index();
|
||||
p_lower_snap := v_index;
|
||||
|
||||
-- Snap SYSSTAT if required...
|
||||
-- ---------------------------
|
||||
if p_include_stat then
|
||||
snap_stats(v_index, true);
|
||||
end if;
|
||||
|
||||
-- Snap ASH if required...
|
||||
-- -----------------------
|
||||
if p_include_ash then
|
||||
for i in 1 .. ceil(v_refresh_rate/g_params(moats.gc_ash_polling_rate)) loop
|
||||
if i > 1 then
|
||||
v_index := snap_index;
|
||||
end if;
|
||||
snap_ash(v_index);
|
||||
dbms_lock.sleep(g_params(moats.gc_ash_polling_rate));
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
-- If no ASH samples taken, sleep for refresh rate instead...
|
||||
-- ----------------------------------------------------------
|
||||
if p_include_stat and not p_include_ash then
|
||||
dbms_lock.sleep(v_refresh_rate);
|
||||
v_index := snap_index;
|
||||
end if;
|
||||
|
||||
-- Snap SYSSTAT again if required...
|
||||
-- ---------------------------------
|
||||
if p_include_stat then
|
||||
snap_stats(v_index);
|
||||
end if;
|
||||
|
||||
-- Set end snap index...
|
||||
-- ---------------------
|
||||
p_upper_snap := v_index;
|
||||
|
||||
end poll;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Determine ASH trailing window size
|
||||
----------------------------------------------------------------------------
|
||||
function get_ash_window_lower_snap (
|
||||
p_lower_snap in pls_integer,
|
||||
p_upper_snap in pls_integer,
|
||||
p_refresh_rate in pls_integer,
|
||||
p_ash_window_size in pls_integer
|
||||
) return pls_integer is
|
||||
|
||||
v_snap_count pls_integer;
|
||||
v_snap pls_integer;
|
||||
v_ash_window_size pls_integer;
|
||||
begin
|
||||
v_ash_window_size := nvl(p_ash_window_size, get_parameter(moats.gc_ash_window_size));
|
||||
-- By default no ASH trailing window or if refresh rate greater than window size
|
||||
-- -----------------------------------------------------------------------------
|
||||
if v_ash_window_size is null or p_refresh_rate >= v_ash_window_size then
|
||||
v_snap := p_lower_snap;
|
||||
else
|
||||
v_snap_count := 1;
|
||||
v_snap := p_upper_snap;
|
||||
while v_snap_count < v_ash_window_size and g_ash.prior(v_snap) is not null loop
|
||||
v_snap_count := v_snap_count + 1;
|
||||
v_snap := g_ash.prior(v_snap);
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
return v_snap;
|
||||
end get_ash_window_lower_snap;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function top (
|
||||
p_refresh_rate in integer default null,
|
||||
p_ash_window_size in integer default null
|
||||
) return moats_output_ntt pipelined is
|
||||
|
||||
v_lower_snap pls_integer;
|
||||
v_upper_snap pls_integer;
|
||||
v_row varchar2(4000);
|
||||
v_rows moats_output_ntt := moats_output_ntt();
|
||||
v_cnt pls_integer := 0;
|
||||
|
||||
begin
|
||||
|
||||
-- Initial clear screen and stabiliser...
|
||||
-- --------------------------------------
|
||||
v_rows := banner();
|
||||
-- fill the initial "blank screen" (this is needed for arraysize = 72 to work)
|
||||
for i in 1 .. gc_screen_size loop
|
||||
pipe row (gc_space);
|
||||
end loop;
|
||||
-- print banner onto the top of the screen
|
||||
for i in 1 .. v_rows.count loop
|
||||
pipe row (v_rows(i));
|
||||
end loop;
|
||||
-- fill the rest of the visible screen
|
||||
for i in 1 .. gc_screen_size-(v_rows.count+1) loop
|
||||
pipe row (gc_space);
|
||||
end loop;
|
||||
pipe row (moats_output_ot('Please wait : fetching data for first refresh...'));
|
||||
|
||||
-- Begin TOP refreshes...
|
||||
-- ----------------------
|
||||
loop
|
||||
|
||||
-- Clear screen...
|
||||
-- ---------------
|
||||
for i in 1 .. gc_screen_size loop
|
||||
pipe row (gc_space);
|
||||
end loop;
|
||||
|
||||
-- Take some ASH/STAT samples...
|
||||
-- -----------------------------
|
||||
poll( p_refresh_rate => p_refresh_rate,
|
||||
p_include_ash => true,
|
||||
p_include_stat => true,
|
||||
p_lower_snap => v_lower_snap,
|
||||
p_upper_snap => v_upper_snap );
|
||||
|
||||
-- pipe row (moats_output_ot('Lower snap: ' || v_lower_snap || ' Upper snap: ' || v_upper_snap));
|
||||
|
||||
-- Banner...
|
||||
-- ---------
|
||||
v_rows := banner();
|
||||
for i in 1 .. v_rows.count loop
|
||||
pipe row (v_rows(i));
|
||||
end loop;
|
||||
pipe row (gc_space);
|
||||
v_cnt := v_rows.count + 1;
|
||||
|
||||
-- Instance summary...
|
||||
-- -------------------
|
||||
v_rows := instance_summary( p_lower_snap => v_lower_snap,
|
||||
p_upper_snap => v_upper_snap );
|
||||
for i in 1 .. v_rows.count loop
|
||||
pipe row (v_rows(i));
|
||||
end loop;
|
||||
pipe row (gc_space);
|
||||
v_cnt := v_cnt + v_rows.count + 1;
|
||||
|
||||
v_lower_snap := get_ash_window_lower_snap( p_lower_snap => v_lower_snap,
|
||||
p_upper_snap => v_upper_snap,
|
||||
p_refresh_rate => p_refresh_rate,
|
||||
p_ash_window_size => p_ash_window_size );
|
||||
|
||||
-- pipe row (moats_output_ot('Lower snap: ' || v_lower_snap || ' Upper snap: ' || v_upper_snap));
|
||||
|
||||
-- Top SQL and waits section...
|
||||
-- ----------------------------
|
||||
v_rows := top_summary( p_lower_snap => v_lower_snap,
|
||||
p_upper_snap => v_upper_snap );
|
||||
for i in 1 .. v_rows.count loop
|
||||
pipe row (v_rows(i));
|
||||
end loop;
|
||||
pipe row (gc_space);
|
||||
v_cnt := v_cnt + v_rows.count + 1;
|
||||
|
||||
-- Some blank output...
|
||||
-- --------------------
|
||||
if v_cnt < (gc_screen_size) then
|
||||
for i in 1 .. (gc_screen_size)-v_cnt loop
|
||||
pipe row (gc_space);
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
end loop;
|
||||
return;
|
||||
|
||||
exception
|
||||
when NO_DATA_FOUND then
|
||||
raise_application_error(-20000, 'Error: '||sqlerrm||' at:'||chr(10)||dbms_utility.format_error_backtrace);
|
||||
end top;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function ash (
|
||||
p_refresh_rate in integer default null,
|
||||
p_select in varchar2 default null,
|
||||
p_where in varchar2 default null,
|
||||
p_group_by in varchar2 default null,
|
||||
p_order_by in varchar2 default null
|
||||
) return moats_output_ntt pipelined is
|
||||
|
||||
v_lower_snap pls_integer;
|
||||
v_upper_snap pls_integer;
|
||||
v_row varchar2(4000);
|
||||
v_cnt pls_integer := 0;
|
||||
|
||||
-- DBMS_SQL variables...
|
||||
-- ---------------------
|
||||
v_sql varchar2(32767);
|
||||
v_cursor binary_integer;
|
||||
v_execute integer;
|
||||
v_desc dbms_sql.desc_tab2;
|
||||
v_cols integer;
|
||||
v_value varchar2(4000);
|
||||
|
||||
begin
|
||||
|
||||
-- Build up the dynamic SQL...
|
||||
-- ---------------------------
|
||||
v_sql := get_sql( p_select => p_select,
|
||||
p_from => 'TABLE(moats.get_ash(:b1, :b2))',
|
||||
p_where => p_where,
|
||||
p_group_by => p_group_by,
|
||||
p_order_by => p_order_by );
|
||||
|
||||
-- Open a cursor for the ASH queries, parse and describe it...
|
||||
-- -----------------------------------------------------------
|
||||
v_cursor := dbms_sql.open_cursor;
|
||||
dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);
|
||||
dbms_sql.describe_columns2(v_cursor, v_cols, v_desc);
|
||||
|
||||
-- Take some ASH samples...
|
||||
-- ------------------------
|
||||
poll( p_refresh_rate => p_refresh_rate,
|
||||
p_include_ash => true,
|
||||
p_include_stat => false,
|
||||
p_lower_snap => v_lower_snap,
|
||||
p_upper_snap => v_upper_snap );
|
||||
|
||||
-- Bind the ASH snapshots...
|
||||
-- -------------------------
|
||||
dbms_sql.bind_variable(v_cursor, 'b1', v_lower_snap);
|
||||
dbms_sql.bind_variable(v_cursor, 'b2', v_upper_snap);
|
||||
|
||||
-- Define the columns and variable we are fetching into...
|
||||
-- -------------------------------------------------------
|
||||
for i in 1 .. v_cols loop
|
||||
dbms_sql.define_column(v_cursor, i, v_value, 4000);
|
||||
end loop;
|
||||
|
||||
-- Output the heading...
|
||||
-- ---------------------
|
||||
for i in 1 .. v_cols loop
|
||||
v_row := v_row || '|' || v_desc(i).col_name;
|
||||
end loop;
|
||||
pipe row (moats_output_ot(v_row));
|
||||
v_row := null;
|
||||
|
||||
-- Start fetching...
|
||||
-- -----------------
|
||||
v_execute := dbms_sql.execute(v_cursor);
|
||||
|
||||
while dbms_sql.fetch_rows(v_cursor) > 0 loop
|
||||
for i in 1 .. v_cols loop
|
||||
dbms_sql.column_value(v_cursor, i, v_value);
|
||||
v_row := v_row || '|' || v_value;
|
||||
end loop;
|
||||
pipe row (moats_output_ot(v_row));
|
||||
v_row := null;
|
||||
end loop;
|
||||
dbms_sql.close_cursor(v_cursor); --<-- will never be reached on an infinite loop with ctrl-c
|
||||
|
||||
return;
|
||||
|
||||
exception
|
||||
when others then
|
||||
dbms_sql.close_cursor(v_cursor);
|
||||
raise_application_error (-20000, 'Error: ' || sqlerrm || ' at:' || chr(10) || dbms_utility.format_error_backtrace, true);
|
||||
end ash;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
function get_ash (
|
||||
p_lower_snap in pls_integer default null,
|
||||
p_upper_snap in pls_integer default null,
|
||||
p_return_set in pls_integer default moats.gc_all_rows
|
||||
) return moats_ash_ntt pipelined is
|
||||
v_lower_snap pls_integer := nvl(p_lower_snap, g_ash.first);
|
||||
v_upper_snap pls_integer := nvl(p_upper_snap, g_ash.last);
|
||||
v_snap pls_integer;
|
||||
v_exit boolean := false;
|
||||
begin
|
||||
v_snap := v_lower_snap;
|
||||
while v_snap is not null and not v_exit loop
|
||||
for i in 1 .. g_ash(v_snap).count loop
|
||||
-- Ignore dummy records
|
||||
if g_ash(v_snap)(i).sid is not null then
|
||||
pipe row (g_ash(v_snap)(i));
|
||||
end if;
|
||||
end loop;
|
||||
v_exit := (v_snap = v_upper_snap);
|
||||
v_snap := case p_return_set
|
||||
when moats.gc_all_rows
|
||||
then g_ash.next(v_snap)
|
||||
else v_upper_snap
|
||||
end;
|
||||
end loop;
|
||||
return;
|
||||
end get_ash;
|
||||
|
||||
begin
|
||||
restore_default_parameters();
|
||||
end moats;
|
||||
/
|
||||
|
||||
|
||||
80
tpt/tools/moats_v1.05/moats.pks
Normal file
80
tpt/tools/moats_v1.05/moats.pks
Normal file
@@ -0,0 +1,80 @@
|
||||
create or replace package moats as
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- MOATS v1.0 (c) Tanel Poder & Adrian Billington, 2010
|
||||
--
|
||||
-- See supplied README.txt for usage and disclaimers.
|
||||
--
|
||||
-- http://www.e2sn.com
|
||||
-- http://www.oracle-developer.net
|
||||
-- --------------------------------------------------------------------------
|
||||
|
||||
-- Pipelined function to show TOP instance summary activity. The refresh rate
|
||||
-- defines how many ASH/SYSSTAT samples to take and is roughly equivalent to
|
||||
-- the number of seconds between screen refreshes...
|
||||
-- --------------------------------------------------------------------------
|
||||
function top (
|
||||
p_refresh_rate in integer default null,
|
||||
p_ash_window_size in integer default null
|
||||
) return moats_output_ntt pipelined;
|
||||
|
||||
-- Helper procedure to size window to TOP output...
|
||||
-- --------------------------------------------------------------------------
|
||||
procedure format_window;
|
||||
|
||||
-- Internal Use Only
|
||||
-- -----------------
|
||||
-- All functions and procedures from this point onwards are for internal use
|
||||
-- only in v1.01. Some of these will be exposed in future versions of MOATS.
|
||||
|
||||
-- Pipelined function to return dynamic samples, queries, aggregations etc
|
||||
-- of active session data. The refresh rate defines (in seconds) how many
|
||||
-- ASH samples to take before running the query components...
|
||||
-- --------------------------------------------------------------------------
|
||||
function ash (
|
||||
p_refresh_rate in integer default null,
|
||||
p_select in varchar2 default null,
|
||||
p_where in varchar2 default null,
|
||||
p_group_by in varchar2 default null,
|
||||
p_order_by in varchar2 default null
|
||||
) return moats_output_ntt pipelined;
|
||||
|
||||
-- Until 11g you can't bind UDTs into DBMS_SQL cursors, so this is an
|
||||
-- internal workaround. Can also be used to query all of the collected ASH
|
||||
-- samples. Note that gc_all_rows returns all ASH records between the two
|
||||
-- snapshots and gc_deltas returns only the lower and upper snapshots...
|
||||
-- --------------------------------------------------------------------------
|
||||
gc_all_rows constant pls_integer := 0;
|
||||
gc_deltas constant pls_integer := 1;
|
||||
|
||||
function get_ash (
|
||||
p_lower_snap in pls_integer default null,
|
||||
p_upper_snap in pls_integer default null,
|
||||
p_return_set in pls_integer default moats.gc_all_rows
|
||||
) return moats_ash_ntt pipelined;
|
||||
|
||||
-- Constants, get/set for moats parameters such as polling rate, ASH size...
|
||||
-- --------------------------------------------------------------------------
|
||||
gc_ash_polling_rate constant pls_integer := 0;
|
||||
gc_ash_threshold constant pls_integer := 1;
|
||||
gc_top_refresh_rate constant pls_integer := 2;
|
||||
gc_ash_window_size constant pls_integer := 3;
|
||||
|
||||
procedure set_parameter(
|
||||
p_parameter_code in pls_integer,
|
||||
p_parameter_value in integer
|
||||
);
|
||||
|
||||
function get_parameter(
|
||||
p_parameter_code in pls_integer
|
||||
) return integer;
|
||||
|
||||
procedure restore_default_parameters;
|
||||
|
||||
-- Debugging...
|
||||
-- --------------------------------------------------------------------------
|
||||
procedure show_snaps;
|
||||
|
||||
end moats;
|
||||
/
|
||||
|
||||
44
tpt/tools/moats_v1.05/moats_install.sql
Normal file
44
tpt/tools/moats_v1.05/moats_install.sql
Normal file
@@ -0,0 +1,44 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
set define off
|
||||
set pause on
|
||||
|
||||
prompt
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt MOATS Installer (for 10.2+ databases)
|
||||
prompt =====================================
|
||||
prompt
|
||||
prompt This will install MOATS v1.0 into the current schema.
|
||||
prompt
|
||||
prompt Ensure that the target schema has the necessary privileges described
|
||||
prompt in the README.txt file.
|
||||
prompt
|
||||
prompt To continue press Enter. To quit press Ctrl-C.
|
||||
prompt
|
||||
prompt (c) oracle-developer.net & www.e2sn.com
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt
|
||||
|
||||
pause
|
||||
|
||||
prompt Creating types...
|
||||
@@moats_types.sql
|
||||
|
||||
prompt Creating package...
|
||||
@@moats.pks
|
||||
@@moats.pkb
|
||||
|
||||
prompt Creating view...
|
||||
@@moats_views.sql
|
||||
|
||||
set define on
|
||||
set pause off
|
||||
|
||||
44
tpt/tools/moats_v1.05/moats_privs_grant.sql
Normal file
44
tpt/tools/moats_v1.05/moats_privs_grant.sql
Normal file
@@ -0,0 +1,44 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
set pause on
|
||||
|
||||
define moats_priv_target = &moats_priv_target;
|
||||
|
||||
prompt
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt MOATS Installer: Privileges
|
||||
prompt ===========================
|
||||
prompt
|
||||
prompt This will grant required privileges to &moats_priv_target..
|
||||
prompt
|
||||
prompt To continue press Enter. To quit press Ctrl-C.
|
||||
prompt
|
||||
prompt (c) oracle-developer.net, www.e2sn.com
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt
|
||||
|
||||
pause
|
||||
|
||||
grant create view to &moats_priv_target;
|
||||
grant create type to &moats_priv_target;
|
||||
grant create table to &moats_priv_target;
|
||||
grant create procedure to &moats_priv_target;
|
||||
grant execute on dbms_lock to &moats_priv_target;
|
||||
grant select on v_$session to &moats_priv_target;
|
||||
grant select on v_$statname to &moats_priv_target;
|
||||
grant select on v_$sysstat to &moats_priv_target;
|
||||
grant select on v_$latch to &moats_priv_target;
|
||||
grant select on v_$timer to &moats_priv_target;
|
||||
grant select on v_$sql to &moats_priv_target;
|
||||
|
||||
undefine moats_priv_target;
|
||||
|
||||
set pause off
|
||||
45
tpt/tools/moats_v1.05/moats_privs_revoke.sql
Normal file
45
tpt/tools/moats_v1.05/moats_privs_revoke.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
set define on
|
||||
set pause on
|
||||
|
||||
define moats_priv_target = &moats_priv_target;
|
||||
|
||||
prompt
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt MOATS Uninstaller: Revoke Privileges
|
||||
prompt ====================================
|
||||
prompt
|
||||
prompt This will revoke MOATS privileges from &moats_priv_target..
|
||||
prompt
|
||||
prompt To continue press Enter. To quit press Ctrl-C.
|
||||
prompt
|
||||
prompt (c) oracle-developer.net, www.e2sn.com
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt
|
||||
|
||||
pause
|
||||
|
||||
revoke create view from &moats_priv_target;
|
||||
revoke create type from &moats_priv_target;
|
||||
revoke create table from &moats_priv_target;
|
||||
revoke create procedure from &moats_priv_target;
|
||||
revoke execute on dbms_lock from &moats_priv_target;
|
||||
revoke select on v_$session from &moats_priv_target;
|
||||
revoke select on v_$statname from &moats_priv_target;
|
||||
revoke select on v_$sysstat from &moats_priv_target;
|
||||
revoke select on v_$latch from &moats_priv_target;
|
||||
revoke select on v_$timer from &moats_priv_target;
|
||||
revoke select on v_$sql from &moats_priv_target;
|
||||
|
||||
undefine moats_priv_target;
|
||||
|
||||
set pause off
|
||||
46
tpt/tools/moats_v1.05/moats_remove.sql
Normal file
46
tpt/tools/moats_v1.05/moats_remove.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
set define off
|
||||
set pause on
|
||||
|
||||
prompt
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt MOATS Uninstaller
|
||||
prompt =================
|
||||
prompt
|
||||
prompt This will uninstall MOATS.
|
||||
prompt
|
||||
prompt To continue press Enter. To quit press Ctrl-C.
|
||||
prompt
|
||||
prompt (c) oracle-developer.net & www.e2sn.com
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt **************************************************************************
|
||||
prompt
|
||||
prompt
|
||||
|
||||
pause
|
||||
|
||||
prompt Removing MOATS...
|
||||
|
||||
drop view top;
|
||||
drop package moats;
|
||||
drop type moats_output_ntt;
|
||||
drop type moats_output_ot;
|
||||
drop type moats_v2_ntt;
|
||||
drop type moats_ash_ntt;
|
||||
drop type moats_ash_ot;
|
||||
drop type moats_stat_ntt;
|
||||
drop type moats_stat_ot;
|
||||
|
||||
prompt
|
||||
prompt
|
||||
prompt **************************************************************************
|
||||
prompt Uninstall complete.
|
||||
prompt **************************************************************************
|
||||
|
||||
9
tpt/tools/moats_v1.05/moats_settings.sql
Normal file
9
tpt/tools/moats_v1.05/moats_settings.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
set arrays 36
|
||||
set lines 110
|
||||
set head off
|
||||
set tab off
|
||||
set serveroutput on format wrapped
|
||||
110
tpt/tools/moats_v1.05/moats_types.sql
Normal file
110
tpt/tools/moats_v1.05/moats_types.sql
Normal file
@@ -0,0 +1,110 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
create type moats_v2_ntt as table of varchar2(4000);
|
||||
/
|
||||
|
||||
create type moats_output_ot as object
|
||||
( output varchar2(4000)
|
||||
);
|
||||
/
|
||||
|
||||
create type moats_output_ntt as table of moats_output_ot;
|
||||
/
|
||||
|
||||
create type moats_ash_ot as object
|
||||
( snaptime timestamp
|
||||
, saddr raw(8)
|
||||
, sid number
|
||||
, serial# number
|
||||
, audsid number
|
||||
, paddr raw(8)
|
||||
, user# number
|
||||
, username varchar2(64)
|
||||
, command number
|
||||
, ownerid number
|
||||
, taddr varchar2(64)
|
||||
, lockwait varchar2(64)
|
||||
, status varchar2(64)
|
||||
, server varchar2(64)
|
||||
, schema# number
|
||||
, schemaname varchar2(64)
|
||||
, osuser varchar2(64)
|
||||
, process varchar2(64)
|
||||
, machine varchar2(64)
|
||||
, terminal varchar2(64)
|
||||
, program varchar2(64)
|
||||
, type varchar2(64)
|
||||
, sql_address raw(8)
|
||||
, sql_hash_value number
|
||||
, sql_id varchar2(64)
|
||||
, sql_child_number number
|
||||
, prev_sql_addr raw(8)
|
||||
, prev_hash_value number
|
||||
, prev_sql_id varchar2(64)
|
||||
, prev_child_number number
|
||||
, module varchar2(64)
|
||||
, module_hash number
|
||||
, action varchar2(64)
|
||||
, action_hash number
|
||||
, client_info varchar2(64)
|
||||
, fixed_table_sequence number
|
||||
, row_wait_obj# number
|
||||
, row_wait_file# number
|
||||
, row_wait_block# number
|
||||
, row_wait_row# number
|
||||
, logon_time date
|
||||
, last_call_et number
|
||||
, pdml_enabled varchar2(64)
|
||||
, failover_type varchar2(64)
|
||||
, failover_method varchar2(64)
|
||||
, failed_over varchar2(64)
|
||||
, resource_consumer_group varchar2(64)
|
||||
, pdml_status varchar2(64)
|
||||
, pddl_status varchar2(64)
|
||||
, pq_status varchar2(64)
|
||||
, current_queue_duration number
|
||||
, client_identifier varchar2(64)
|
||||
, blocking_session_status varchar2(64)
|
||||
, blocking_instance number
|
||||
, blocking_session number
|
||||
, seq# number
|
||||
, event# number
|
||||
, event varchar2(64)
|
||||
, p1text varchar2(64)
|
||||
, p1 number
|
||||
, p1raw raw(8)
|
||||
, p2text varchar2(64)
|
||||
, p2 number
|
||||
, p2raw raw(8)
|
||||
, p3text varchar2(64)
|
||||
, p3 number
|
||||
, p3raw raw(8)
|
||||
, wait_class_id number
|
||||
, wait_class# number
|
||||
, wait_class varchar2(64)
|
||||
, wait_time number
|
||||
, seconds_in_wait number
|
||||
, state varchar2(64)
|
||||
, service_name varchar2(64)
|
||||
, sql_trace varchar2(64)
|
||||
, sql_trace_waits varchar2(64)
|
||||
, sql_trace_binds varchar2(64)
|
||||
);
|
||||
/
|
||||
|
||||
create type moats_ash_ntt as table of moats_ash_ot;
|
||||
/
|
||||
|
||||
create type moats_stat_ot as object
|
||||
( type varchar2(100)
|
||||
, name varchar2(100)
|
||||
, value number
|
||||
);
|
||||
/
|
||||
|
||||
create type moats_stat_ntt as table of moats_stat_ot;
|
||||
/
|
||||
|
||||
|
||||
8
tpt/tools/moats_v1.05/moats_views.sql
Normal file
8
tpt/tools/moats_v1.05/moats_views.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
create or replace view top
|
||||
as
|
||||
select *
|
||||
from table(moats.top);
|
||||
19
tpt/tools/moats_v1.05/top.sql
Normal file
19
tpt/tools/moats_v1.05/top.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
-- Following settings should be mandatory and documented...
|
||||
-- --------------------------------------------------------
|
||||
set arrays 72
|
||||
set lines 110
|
||||
set head off
|
||||
set tab off
|
||||
set pages 0
|
||||
|
||||
-- Windows sqlplus properties for optimal output (relative to font):
|
||||
-- * font: lucide console 12
|
||||
-- * window size: height of 47
|
||||
|
||||
select * from table(moats.top(5));
|
||||
|
||||
|
||||
45
tpt/tools/optimizer/descxx_install.sql
Normal file
45
tpt/tools/optimizer/descxx_install.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- descxx.sql requires the display_raw function which is included in the comment section below.
|
||||
-- the display_raw function is taken from Greg Rahn's blog as I'm too lazy to write one myself
|
||||
-- http://structureddata.org/2007/10/16/how-to-display-high_valuelow_value-columns-from-user_tab_col_statistics/
|
||||
--
|
||||
|
||||
PROMPT Install DISPLAY_RAW helper function into the current schema?
|
||||
PAUSE Press ENTER to install, CTRL+C to cancel...
|
||||
|
||||
create or replace function display_raw (rawval raw, type varchar2)
|
||||
return varchar2
|
||||
is
|
||||
cn number;
|
||||
cv varchar2(128);
|
||||
cd date;
|
||||
cnv nvarchar2(128);
|
||||
cr rowid;
|
||||
cc char(128);
|
||||
begin
|
||||
if (type = 'NUMBER') then
|
||||
dbms_stats.convert_raw_value(rawval, cn);
|
||||
return to_char(cn);
|
||||
elsif (type = 'VARCHAR2') then
|
||||
dbms_stats.convert_raw_value(rawval, cv);
|
||||
return to_char(cv);
|
||||
elsif (type = 'DATE') then
|
||||
dbms_stats.convert_raw_value(rawval, cd);
|
||||
return to_char(cd);
|
||||
elsif (type = 'NVARCHAR2') then
|
||||
dbms_stats.convert_raw_value(rawval, cnv);
|
||||
return to_char(cnv);
|
||||
elsif (type = 'ROWID') then
|
||||
dbms_stats.convert_raw_value(rawval, cr);
|
||||
return to_char(cnv);
|
||||
elsif (type = 'CHAR') then
|
||||
dbms_stats.convert_raw_value(rawval, cc);
|
||||
return to_char(cc);
|
||||
else
|
||||
return 'UNKNOWN DATATYPE';
|
||||
end if;
|
||||
end;
|
||||
/
|
||||
|
||||
grant execute on display_raw to public;
|
||||
create public synonym display_raw for display_raw;
|
||||
|
||||
37
tpt/tools/optimizer/optimizer_features_matrix.sql
Normal file
37
tpt/tools/optimizer/optimizer_features_matrix.sql
Normal file
@@ -0,0 +1,37 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
PROMPT display a matrix of optimizer parameters which change when changing optimizer_features_enabled...
|
||||
|
||||
CREATE TABLE opt_param_matrix(
|
||||
opt_features_enabled VARCHAR2(20) NOT NULL
|
||||
, parameter VARCHAR2(75) NOT NULL
|
||||
, value VARCHAR2(1000)
|
||||
)
|
||||
/
|
||||
|
||||
CREATE TABLE opt_fix_matrix (
|
||||
opt_features_enabled VARCHAR2(20) NOT NULL
|
||||
, bugno NUMBER
|
||||
, value NUMBER
|
||||
, sql_feature VARCHAR2(100)
|
||||
, description VARCHAR2(100)
|
||||
, optimizer_feature_enable VARCHAR2(25)
|
||||
, event NUMBER
|
||||
, is_default NUMBER
|
||||
)
|
||||
/
|
||||
|
||||
BEGIN
|
||||
FOR i IN (select value from v$parameter_valid_values where name = 'optimizer_features_enable' order by ordinal) LOOP
|
||||
EXECUTE IMMEDIATE 'alter session set optimizer_features_enable='''||i.value||'''';
|
||||
EXECUTE IMMEDIATE 'insert into opt_param_matrix select :opt_features_enable, n.ksppinm, c.ksppstvl from sys.x$ksppi n, sys.x$ksppcv c where n.indx=c.indx' using i.value;
|
||||
EXECUTE IMMEDIATE 'insert into opt_fix_matrix select :opt_features_enable, bugno, value, sql_feature, description, optimizer_feature_enable, event, is_default FROM v$session_fix_control WHERE session_id=USERENV(''sid'')' using i.value;
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT To test, run: @cofep.sql 10.2.0.1 10.2.0.4
|
||||
|
||||
25
tpt/tools/optimizer/sqlflame_stacks.txt
Normal file
25
tpt/tools/optimizer/sqlflame_stacks.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY 1
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY 45
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER 20
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS 19
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS 66
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN 635
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;7 - TABLE ACCESS FULL [TPCDS.DATE_DIM] 3
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN 935
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;9 - TABLE ACCESS FULL [TPCDS.HOUSEHOLD_DEMOGRAPHICS] 4
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN 146490
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN 11104
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;12 - TABLE ACCESS FULL [TPCDS.WAREHOUSE] 5
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN 20788
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN;14 - HASH JOIN 3
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN;14 - HASH JOIN;15 - TABLE ACCESS FULL [TPCDS.DATE_DIM] 3
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN;14 - HASH JOIN;16 - TABLE ACCESS FULL [TPCDS.DATE_DIM] 3
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN;17 - PARTITION RANGE ALL 113
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;11 - HASH JOIN;13 - HASH JOIN;17 - PARTITION RANGE ALL;18 - TABLE ACCESS FULL [TPCDS.INVENTORY] 5683
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;19 - PARTITION RANGE ALL 4635
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;6 - HASH JOIN;8 - HASH JOIN;10 - HASH JOIN;19 - PARTITION RANGE ALL;20 - TABLE ACCESS FULL [TPCDS.CATALOG_SALES] 13397
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;21 - TABLE ACCESS BY INDEX ROWID [TPCDS.CUSTOMER_DEMOGRAPHICS] 2552
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;5 - NESTED LOOPS;21 - TABLE ACCESS BY INDEX ROWID [TPCDS.CUSTOMER_DEMOGRAPHICS];22 - INDEX UNIQUE SCAN [TPCDS.CD_DEMO_PK_IDX] 475
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;23 - TABLE ACCESS BY INDEX ROWID [TPCDS.ITEM] 50
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;4 - NESTED LOOPS;23 - TABLE ACCESS BY INDEX ROWID [TPCDS.ITEM];24 - INDEX UNIQUE SCAN [TPCDS.ITEM_PK_IDX] 167
|
||||
0 - SELECT STATEMENT;1 - SORT ORDER BY;2 - HASH GROUP BY;3 - NESTED LOOPS OUTER;25 - INDEX UNIQUE SCAN [TPCDS.PROMOTION_PK_IDX] 32
|
||||
106
tpt/tools/poor_ash/poor_ash.sh
Normal file
106
tpt/tools/poor_ash/poor_ash.sh
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
# note that "*" doesn't go well together with unix shell, so don't use it in your queries
|
||||
HEADERQUERY="SELECT
|
||||
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') sample_time
|
||||
, sid
|
||||
, serial#
|
||||
, username
|
||||
, CASE WHEN state != 'WAITING' THEN 'ON CPU' ELSE 'WAITING' END AS state
|
||||
, CASE WHEN state != 'WAITING' THEN 'On CPU / runqueue' ELSE event END AS event
|
||||
, seq#
|
||||
, seconds_in_wait
|
||||
, blocking_session_status
|
||||
, blocking_session
|
||||
, blocking_instance
|
||||
, program
|
||||
, command
|
||||
, osuser
|
||||
, process
|
||||
, machine
|
||||
, terminal
|
||||
, module
|
||||
, action
|
||||
, client_identifier
|
||||
, client_info
|
||||
, type
|
||||
, sql_id
|
||||
, sql_child_number
|
||||
, TO_CHAR(sql_exec_start, 'YYYY-MM-DD HH24:MI:SS') sql_exec_start
|
||||
, sql_exec_id
|
||||
, p1text
|
||||
, p1raw
|
||||
, p2text
|
||||
, p2raw
|
||||
, p3text
|
||||
, p3raw
|
||||
FROM
|
||||
v\$session s
|
||||
WHERE
|
||||
sid = SYS_CONTEXT('USERENV', 'SID')
|
||||
"
|
||||
|
||||
ASHQUERY="SELECT
|
||||
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') sample_time
|
||||
, sid
|
||||
, serial#
|
||||
, username
|
||||
, CASE WHEN state != 'WAITING' THEN 'ON CPU' ELSE 'WAITING' END AS state
|
||||
, CASE WHEN state != 'WAITING' THEN 'On CPU / runqueue' ELSE event END AS event
|
||||
, seq#
|
||||
, seconds_in_wait
|
||||
, blocking_session_status
|
||||
, blocking_session
|
||||
, blocking_instance
|
||||
, program
|
||||
, command
|
||||
, osuser
|
||||
, process
|
||||
, machine
|
||||
, terminal
|
||||
, module
|
||||
, action
|
||||
, client_identifier
|
||||
, client_info
|
||||
, type
|
||||
, sql_id
|
||||
, sql_child_number
|
||||
, TO_CHAR(sql_exec_start, 'YYYY-MM-DD HH24:MI:SS') sql_exec_start
|
||||
, sql_exec_id
|
||||
, p1text
|
||||
, p1raw
|
||||
, p2text
|
||||
, p2raw
|
||||
, p3text
|
||||
, p3raw
|
||||
FROM
|
||||
v\$session s
|
||||
WHERE
|
||||
(s.status = 'ACTIVE' and s.state != 'WAITING' and s.sid != SYS_CONTEXT('USERENV','SID'))
|
||||
OR
|
||||
( s.status = 'ACTIVE'
|
||||
AND s.state = 'WAITING'
|
||||
AND s.wait_class != 'Idle'
|
||||
AND s.sid != SYS_CONTEXT('USERENV','SID')
|
||||
)
|
||||
"
|
||||
|
||||
echo SET PAGESIZE 50000 LINESIZE 5000 TRIMSPOOL ON TRIMOUT ON TAB OFF FEEDBACK OFF VERIFY OFF COLSEP \",\" SQLPROMPT \"\" SQLNUMBER OFF HEADING ON
|
||||
echo "PROMPT Running... (ignore the first row, it's for printing the column headers...)"
|
||||
echo "$HEADERQUERY"
|
||||
echo "/"
|
||||
|
||||
echo SET HEADING OFF
|
||||
echo "$ASHQUERY"
|
||||
|
||||
# LOOP FOREVER
|
||||
while true
|
||||
do
|
||||
|
||||
sleep 1
|
||||
echo "/"
|
||||
|
||||
done
|
||||
|
||||
4
tpt/tools/poor_ash/run_poor_ash.sh
Normal file
4
tpt/tools/poor_ash/run_poor_ash.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
./poor_ash.sh | sqlplus "/ as sysasm" > log_poor_ash.txt
|
||||
|
||||
93
tpt/tools/session_wait_monitor.sql
Normal file
93
tpt/tools/session_wait_monitor.sql
Normal file
@@ -0,0 +1,93 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--
|
||||
-- SCRIPT: session_wait_monitor.sql
|
||||
--
|
||||
-- PURPOSE: Creates one table and one procedure for logging v$session_wait
|
||||
-- wait statistics. Running this script does not enable the logging,
|
||||
-- the usage examples are below.
|
||||
--
|
||||
-- REQUIREMENTS:
|
||||
-- Read access on V$SESSION_WAIT
|
||||
-- Execute right on DBMS_LOCK
|
||||
--
|
||||
-- USAGE:
|
||||
-- EXEC session_wait_monitor ( <wait_name>, <from_time>, <to_time>, <sleep_time> )
|
||||
--
|
||||
-- wait_name = the name of wait event to be sampled, % and _ wildcards allowed, default %
|
||||
-- from_time = time when sampling should start (the procedure sleeps until then), default SYSDATE
|
||||
-- to_time = time when sampling should end (procedure quits then), default SYSDATE + 1 minute
|
||||
-- sleep_time= time to sleep between samples, default 5 seconds
|
||||
--
|
||||
-- once the procedure returns, query session wait samples:
|
||||
--
|
||||
-- SELECT * FROM session_wait_hist ORDER BY sample_time ASC, cnt DESC;
|
||||
--
|
||||
-- EXAMPLES:
|
||||
-- After the table and procedure have been created, use following commands to:
|
||||
--
|
||||
-- 1) Sample all session waits for 60 seconds from now, at 5 second intervals (few idle waits are not sampled):
|
||||
--
|
||||
-- EXEC session_wait_monitor
|
||||
--
|
||||
-- 2) Sample only buffer busy waits from 9 pm to 9:10 pm on 2007-10-19 (3 second sampling interval)
|
||||
--
|
||||
-- EXEC session_wait_monitor('buffer busy waits', timestamp'2007-10-19 21:00:00', timestamp'2007-10-19 21:10:00', 3)
|
||||
--
|
||||
-- 3) Sample all events containing "db" from now up to end of today:
|
||||
--
|
||||
-- EXEC session_wait_monitor('%db%', sysdate, trunc(sysdate)+1)
|
||||
--
|
||||
|
||||
create table session_wait_hist(
|
||||
sample_time date not null,
|
||||
event varchar2(100) not null,
|
||||
p1 number,
|
||||
p2 number,
|
||||
p3 number,
|
||||
cnt number
|
||||
);
|
||||
|
||||
create or replace procedure session_wait_monitor (
|
||||
wait_name in varchar2 default '%',
|
||||
from_time in date default sysdate,
|
||||
to_time in date default sysdate + 1/24/60,
|
||||
sleep_time in number default 5
|
||||
)
|
||||
authid current_user as
|
||||
begin
|
||||
|
||||
while sysdate < from_time loop
|
||||
dbms_lock.sleep(sleep_time);
|
||||
end loop;
|
||||
|
||||
while sysdate between from_time and to_time loop
|
||||
|
||||
insert into
|
||||
session_wait_hist
|
||||
select
|
||||
sysdate, event, p1, p2, p3, count(*) cnt
|
||||
from
|
||||
v$session_wait
|
||||
where
|
||||
state = 'WAITING'
|
||||
and event like wait_name
|
||||
and event not in (
|
||||
'SQL*Net message from client',
|
||||
'pmon timer',
|
||||
'rdbms ipc message',
|
||||
'smon timer',
|
||||
'wakeup time manager'
|
||||
)
|
||||
group by
|
||||
event, p1, p2, p3;
|
||||
|
||||
commit;
|
||||
|
||||
dbms_lock.sleep(sleep_time);
|
||||
|
||||
end loop;
|
||||
|
||||
end;
|
||||
/
|
||||
BIN
tpt/tools/sesspack_0.05_release.zip
Normal file
BIN
tpt/tools/sesspack_0.05_release.zip
Normal file
Binary file not shown.
168
tpt/tools/sesspack_0.05_release/README.txt
Normal file
168
tpt/tools/sesspack_0.05_release/README.txt
Normal file
@@ -0,0 +1,168 @@
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
================================================================================
|
||||
SESSPACK v0.05 readme
|
||||
================================================================================
|
||||
|
||||
About:
|
||||
|
||||
Sesspack can be best described as session level statspack for Oracle.
|
||||
It collects less data than statspack, "only" the session level wait events
|
||||
and v$sesstat info and stores it in its repository.
|
||||
|
||||
However Sesspack allows you to select the sampled sessions very flexibly,
|
||||
you can sample all sessions in an instance or only few, based on various
|
||||
conditions like SID, username, osuser, program, client machine, currently
|
||||
effective module and action etc.
|
||||
|
||||
Sesspack doesn't add extra instrumentation overhead to the database, it
|
||||
just queries v$session_event, v$sesstat and few other views when executed.
|
||||
|
||||
Note that with large number of sessions (1000+) you may want to sample
|
||||
sessions selectively to save disk space and reduce snapshot CPU usage
|
||||
|
||||
For further information, see http://www.tanelpoder.com
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
1) Using SQLPLUS, log on as user who can *grant* access on V$ views (SYS for example)
|
||||
|
||||
2) Create a user if want to have sesspack object in separate schema and grant connect to it
|
||||
|
||||
3) run install_sesspack.sql <username> <password> <connect_string>
|
||||
|
||||
e.g. @install_sesspack sesspack mypassword prod01
|
||||
|
||||
4) check sesspack_install.log
|
||||
|
||||
Usage example:
|
||||
|
||||
Note that the reports require fairly wide linesize (120+)
|
||||
|
||||
1) exec sesspack.snap_orauser('<USERNAME>')
|
||||
2) do some work
|
||||
3) exec sesspack.snap_orauser('<USERNAME>')
|
||||
4) @list
|
||||
5) @sr sid,program 1 2
|
||||
|
||||
This will take snapshot 1 and 2 of user <USERNAME>
|
||||
|
||||
|
||||
Reference:
|
||||
|
||||
Taking snapshots:
|
||||
|
||||
sesspack.snap_me - snaps current session stats
|
||||
sesspack.snap_sid - snaps given SIDs stats
|
||||
sesspack.snap_orauser('<orauser>') - snaps all given ORACLE user's sessions's stats
|
||||
sesspack.snap_osuser('<osuser>') - snaps all given OS user's sessions's stats
|
||||
sesspack.snap_program('<program>') - snaps all given programs session stats
|
||||
sesspack.snap_machine('<machine>') - snaps all given machines session stats
|
||||
sesspack.snap_spid('spid') - snaps all given SPID session stats
|
||||
sesspack.snap_cpid('cpid') - snaps all given client PID session stats
|
||||
sesspack.snap_all - snaps all session stats
|
||||
sesspack.snap_bg - snaps background processes sessions stats
|
||||
sesspack.snap_fg - snaps foreground processes sessions stats
|
||||
|
||||
sesspack.snap_sidlist_internal('select sid from v$sesstat where <your custom conditions>')
|
||||
- snaps all SIDs returned by custom SQL
|
||||
|
||||
Reporting performance data:
|
||||
|
||||
list.sql shows you snapshots with brief descriptions
|
||||
|
||||
sr.sql <grouping_col> <x> <y>
|
||||
|
||||
shows you the session event deltas between selected snapshots, grouped by a column
|
||||
|
||||
Columns can be:
|
||||
|
||||
1
|
||||
SID
|
||||
AUDSID
|
||||
SERIAL#
|
||||
USERNAME
|
||||
PROGRAM
|
||||
TERMINAL
|
||||
MACHINE
|
||||
OSUSER
|
||||
PROCESS
|
||||
|
||||
To get a session-level resource usage breakdown, use:
|
||||
|
||||
@sr sid <start> <end>
|
||||
|
||||
To get resource usage summed and rolled up by client program nama, use:
|
||||
|
||||
@sr program <start> <end>
|
||||
|
||||
To get resource usage on sid level but you also want to see other data columns in output,
|
||||
you can combine the columns:
|
||||
|
||||
@sr program,module <start> <end>
|
||||
|
||||
To sum up all measured resource consumption in the snap, use dummy column 1:
|
||||
|
||||
@sr 1 <start> <end>
|
||||
|
||||
|
||||
|
||||
Purging old data:
|
||||
|
||||
1) exec sesspack.purge_data; -- purges all data older than a week
|
||||
or
|
||||
exec sesspack.purge_data(<days_to_keep);
|
||||
2) commit;
|
||||
|
||||
|
||||
Customization:
|
||||
|
||||
For disk space reasons ony the sesspack.snap_me procedure gathers all v$sesstat statistics.
|
||||
Other procedures gather session statistics based on
|
||||
|
||||
|
||||
|
||||
Roadmap/Notes/bugs/issues:
|
||||
|
||||
|
||||
v0.05
|
||||
========
|
||||
|
||||
fixes in gathering snaps & sr report
|
||||
Schema - large tables compressed IOTs
|
||||
performance report allows grouping by any field
|
||||
purge capability
|
||||
|
||||
|
||||
v0.04
|
||||
========
|
||||
customizable template-based session stats sampling
|
||||
more snap procedures
|
||||
|
||||
v0.03b
|
||||
========
|
||||
Using V$SESSION_TIME_MODEL for getting if 10g+
|
||||
|
||||
v0.03
|
||||
========
|
||||
Multi-session snapshots should work ok now
|
||||
I realized that standard-snapshots can't include all v$sesstat contents in snapshot by default - too much data generated
|
||||
This is ok though, as we usually need only CPU time from there anyway.
|
||||
|
||||
V0.02
|
||||
========
|
||||
Lots.
|
||||
Test first with only single Oracle user session - with multiple simultaneous logged on sessions there's some cartesian join somewhere
|
||||
|
||||
|
||||
|
||||
29
tpt/tools/sesspack_0.05_release/drop_grants_syns.sql
Normal file
29
tpt/tools/sesspack_0.05_release/drop_grants_syns.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
drop public synonym sawr$snapshots;
|
||||
drop public synonym sawr$sessions;
|
||||
drop public synonym sawr$session_events;
|
||||
drop public synonym sawr$session_stats;
|
||||
drop public synonym sawr$snapid_seq;
|
||||
drop public synonym sawr$sidlist;
|
||||
|
||||
--drop public synonym sawr$sess_event_delta;
|
||||
drop public synonym sawr$sess_event;
|
||||
drop public synonym sesspack;
|
||||
|
||||
drop public synonym sawr$sess_stat;
|
||||
drop public synonym sawr$session_stat_mode;
|
||||
|
||||
|
||||
37
tpt/tools/sesspack_0.05_release/drop_sesspack.sql
Normal file
37
tpt/tools/sesspack_0.05_release/drop_sesspack.sql
Normal file
@@ -0,0 +1,37 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
define spuser=PERFSTAT
|
||||
define spconn=""
|
||||
|
||||
accept spuser default &spuser prompt "Specify the schema where SAWR and SESSPACK are installed [&spuser]: "
|
||||
accept sppassword prompt "Specify the password for &spuser user: " hide
|
||||
accept spconn prompt "Enter connect string PREFIXED WITH @ if connecting to remote database [&spconn]: "
|
||||
|
||||
-- @@unprepare_user
|
||||
|
||||
connect &spuser/&sppassword&spconn
|
||||
|
||||
prompt Uninstalling schema...
|
||||
|
||||
|
||||
@@drop_sesspack_packages.sql
|
||||
@@drop_sesspack_schema.sql
|
||||
|
||||
prompt Schema uninstalled.
|
||||
prompt
|
||||
|
||||
|
||||
prompt Uninstallation completed.
|
||||
prompt Currently connected as &spuser&spconn....
|
||||
prompt
|
||||
17
tpt/tools/sesspack_0.05_release/drop_sesspack_packages.sql
Normal file
17
tpt/tools/sesspack_0.05_release/drop_sesspack_packages.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
drop package sesspack;
|
||||
|
||||
|
||||
|
||||
28
tpt/tools/sesspack_0.05_release/drop_sesspack_schema.sql
Normal file
28
tpt/tools/sesspack_0.05_release/drop_sesspack_schema.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@drop_grants_syns.sql
|
||||
|
||||
drop view sawr$sess_event;
|
||||
drop view sawr$sess_stat;
|
||||
|
||||
drop sequence sawr$snapid_seq;
|
||||
|
||||
drop table sawr$snapshots;
|
||||
drop table sawr$sessions;
|
||||
drop table sawr$session_events;
|
||||
drop table sawr$session_stats;
|
||||
drop table sawr$session_stat_mode;
|
||||
|
||||
drop type sawr$SIDList;
|
||||
|
||||
52
tpt/tools/sesspack_0.05_release/install_grants_syns.sql
Normal file
52
tpt/tools/sesspack_0.05_release/install_grants_syns.sql
Normal file
@@ -0,0 +1,52 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- grants for procs & types
|
||||
grant execute on sesspack to sesspack_user_role;
|
||||
grant execute on sawr$sidlist to sesspack_user_role;
|
||||
|
||||
-- grants for sequences
|
||||
grant select on sawr$snapid_seq to sesspack_user_role;
|
||||
|
||||
-- grants for tables
|
||||
grant select, insert on sawr$snapshots to sesspack_user_role;
|
||||
grant select, insert on sawr$sessions to sesspack_user_role;
|
||||
grant select, insert on sawr$session_events to sesspack_user_role;
|
||||
grant select, insert on sawr$session_stats to sesspack_user_role;
|
||||
grant select on sawr$session_stat_mode to sesspack_user_role;
|
||||
|
||||
-- grants for views
|
||||
grant select on sawr$sess_event to sesspack_user_role;
|
||||
--grant select on sawr$sess_event_delta to sesspack_user_role;
|
||||
grant select on sawr$sess_stat to sesspack_user_role;
|
||||
|
||||
-- synonyms for procs & types
|
||||
create public synonym sesspack for sesspack;
|
||||
create public synonym sawr$sidlist for sawr$sidlist;
|
||||
|
||||
-- synonyms for sequences
|
||||
create public synonym sawr$snapid_seq for sawr$snapid_seq;
|
||||
|
||||
-- synonyms for tables
|
||||
create public synonym sawr$snapshots for sawr$snapshots;
|
||||
create public synonym sawr$sessions for sawr$sessions;
|
||||
create public synonym sawr$session_events for sawr$session_events;
|
||||
create public synonym sawr$session_stats for sawr$session_stats;
|
||||
create public synonym sawr$session_stat_mode for sawr$session_stat_mode;
|
||||
|
||||
-- synonyms for views
|
||||
create public synonym sawr$sess_event for sawr$sess_event;
|
||||
--create public synonym sawr$sess_event_delta for sawr$sess_event_delta;
|
||||
create public synonym sawr$sess_stat for sawr$sess_stat;
|
||||
|
||||
70
tpt/tools/sesspack_0.05_release/install_osstat.sql
Normal file
70
tpt/tools/sesspack_0.05_release/install_osstat.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- add on script for pre-10g databases which need to record CPU usage
|
||||
-- for long-running calls (as 9i doesnt update session cpu usage in
|
||||
-- v$ views before end of call)
|
||||
--
|
||||
-- this script needs tidying up
|
||||
--
|
||||
|
||||
|
||||
-- rm /tmp/sawr_vmstat_pipe
|
||||
-- rm /tmp/sawr_ps_pipe
|
||||
|
||||
-- mknod /tmp/sawr_vmstat_pipe p
|
||||
-- mknod /tmp/sawr_ps_pipe p
|
||||
|
||||
-- create directory osstat as 'c:/tmp';
|
||||
-- drop directory sawr$osstat;
|
||||
|
||||
create directory sawr$osstat as '/tmp';
|
||||
|
||||
grant read,write on directory sawr$osstat to &spuser;
|
||||
|
||||
|
||||
drop table vmstat;
|
||||
drop table ps;
|
||||
|
||||
CREATE TABLE sawr$ext_vmstat (
|
||||
value number,
|
||||
parameter varchar2(100)
|
||||
)
|
||||
ORGANIZATION EXTERNAL (
|
||||
TYPE oracle_loader
|
||||
DEFAULT DIRECTORY sawr$osstat
|
||||
ACCESS PARAMETERS (
|
||||
FIELDS TERMINATED BY ';'
|
||||
MISSING FIELD VALUES ARE NULL
|
||||
(value, parameter)
|
||||
)
|
||||
LOCATION ('sawr_vmstat_pipe')
|
||||
)
|
||||
;
|
||||
|
||||
CREATE TABLE sawr$ext_ps (
|
||||
ospid varchar2(100),
|
||||
value varchar2(100)
|
||||
)
|
||||
ORGANIZATION EXTERNAL (
|
||||
TYPE oracle_loader
|
||||
DEFAULT DIRECTORY sawr$osstat
|
||||
ACCESS PARAMETERS (
|
||||
FIELDS TERMINATED BY ';'
|
||||
MISSING FIELD VALUES ARE NULL
|
||||
(ospid, value)
|
||||
)
|
||||
LOCATION ('sawr_ps_pipe')
|
||||
)
|
||||
;
|
||||
|
||||
81
tpt/tools/sesspack_0.05_release/install_sesspack.sql
Normal file
81
tpt/tools/sesspack_0.05_release/install_sesspack.sql
Normal file
@@ -0,0 +1,81 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
spool sesspack_install.log
|
||||
|
||||
prompt
|
||||
prompt =================================================================================
|
||||
prompt
|
||||
prompt Welcome to the Semi-Automatic Workload Repository installer!
|
||||
prompt
|
||||
prompt This script will create some SAWR tables and SESSPACK package in specified schema
|
||||
prompt
|
||||
prompt Refer to README.txt for usage and further information
|
||||
prompt
|
||||
prompt (c) Tanel Poder http://www.tanelpoder.com
|
||||
prompt
|
||||
prompt =================================================================================
|
||||
prompt
|
||||
prompt
|
||||
prompt You must be already connected to your target database as SYS or any other user
|
||||
prompt who can grant privileges on some V$ objects for preparing SAWR user
|
||||
prompt
|
||||
|
||||
|
||||
-- this section is for initializing couple of "preprocessor" variables which create
|
||||
-- different PLSQL based on target database version
|
||||
|
||||
column sesspack_v9 noprint new_value version_9_enable
|
||||
column sesspack_v10 noprint new_value version_10_enable
|
||||
|
||||
with SQ as (
|
||||
select substr(
|
||||
substr(banner, instr(banner, 'Release ')+8),
|
||||
1,
|
||||
instr(substr(banner, instr(banner, 'Release ')+8),'.')-1
|
||||
) db_version
|
||||
from v$version
|
||||
where rownum = 1
|
||||
)
|
||||
select
|
||||
case when db_version = '9' then '--' else '/*' end sesspack_v9,
|
||||
case when db_version != '9' then '--' else '/*' end sesspack_v10
|
||||
from sq;
|
||||
-- end of preprocessor initialization
|
||||
|
||||
|
||||
-- Defines for non-interactive installation
|
||||
define spuser="&1"
|
||||
define sppassword="&2"
|
||||
define spconn="@&3"
|
||||
|
||||
-- Uncomment for interactive installation
|
||||
--define spuser="SESSPACK"
|
||||
--define spconn=""
|
||||
--accept spuser default &spuser prompt "Specify the schema for SAWR and SESSPACK installation [&spuser]: "
|
||||
--accept sppassword prompt "Specify the password for &spuser user: " hide
|
||||
--accept spconn prompt "Enter connect string PREFIXED WITH @ if installing into remote database [&spconn]: "
|
||||
|
||||
@@prepare_user.sql
|
||||
|
||||
connect &spuser/&sppassword&spconn
|
||||
|
||||
@@install_sesspack_schema.sql
|
||||
@@install_sesspack_packages.sql
|
||||
@@install_grants_syns.sql
|
||||
|
||||
prompt Installation completed.
|
||||
prompt Currently connected as &spuser&spconn....
|
||||
prompt
|
||||
|
||||
spool off
|
||||
716
tpt/tools/sesspack_0.05_release/install_sesspack_packages.sql
Normal file
716
tpt/tools/sesspack_0.05_release/install_sesspack_packages.sql
Normal file
@@ -0,0 +1,716 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
create or replace package sesspack
|
||||
|
||||
authid definer -- using definer authid so executing users don't have to have explicit grants on
|
||||
-- schema and V$ objects
|
||||
|
||||
-- authid current_user -- safer option, allows use of privileges granted through roles
|
||||
is
|
||||
|
||||
function in_list( p_sql in varchar2 ) return sawr$SIDlist;
|
||||
|
||||
function valid_stat_modes return sawr$ModeList;
|
||||
|
||||
procedure snap_sidlist_internal( p_sidlist in sawr$SIDlist, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
procedure snap_sidlist_internal( p_sql in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap current session
|
||||
procedure snap_me ( p_session_stats in varchar2 default 'ALL', p_snapid in number default null );
|
||||
|
||||
-- snap session with given SID
|
||||
procedure snap_sid ( p_sid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
procedure snap_sid ( p_sid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by oracle user
|
||||
procedure snap_orauser( p_username in varchar2 default user, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by os user
|
||||
procedure snap_osuser( p_username in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by program name (v$session.program)
|
||||
procedure snap_program( p_program in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by terminal (v$session.terminal)
|
||||
procedure snap_terminal( p_terminal in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by machine (v$session.machine)
|
||||
procedure snap_machine( p_machine in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap the session being served by SPID (v$process.spid)
|
||||
procedure snap_spid( p_spid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
procedure snap_spid( p_spid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions by client PID (v$session.process)
|
||||
procedure snap_cpid( p_cpid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
procedure snap_cpid( p_cpid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap all sessions
|
||||
procedure snap_all ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap background sessions
|
||||
procedure snap_bg ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- snap user sessions
|
||||
procedure snap_fg ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
|
||||
|
||||
-- purge repository data
|
||||
procedure purge_data ( p_days_threshold in number default 7, p_snapid in number default null );
|
||||
|
||||
end sesspack;
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
create or replace package body sesspack as
|
||||
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
--
|
||||
-- Global Variables
|
||||
--
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- g_snap_mode is inserted into sawr$snapshots table during first call to assign_snapid()
|
||||
-- the global variable is changed in the beginning of each external procedure which can be
|
||||
-- called directly. this means the directly-called procedure's g_snap_mode will be recorded
|
||||
-- to sawr$snapshots table and its values will be ignored from there on
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
g_snap_mode varchar2(100) := 'Undefined';
|
||||
|
||||
|
||||
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
--
|
||||
-- Internal Procs used by sesspack itself
|
||||
--
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- FUNCTION: assign_snapid
|
||||
-- PURPOSE: generate new snapid if the the parent snap function is executed standalone.
|
||||
-- if its executed from proper top-level function, a snapid to use should have been
|
||||
-- passed down from there.
|
||||
-- the reason for that is that we might need to run several different snap commands
|
||||
-- for getting a snapshot (e.g. get all sessions where USERNAME = 'SYS' and all with
|
||||
-- MODULE='HR')
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function assign_snapid (p_snapid in number, l_snap_comment varchar2 default '' ) return number
|
||||
as
|
||||
l_snapid number;
|
||||
begin
|
||||
if (p_snapid is null) then
|
||||
-- insert a line for each distinct snapshot. primary method of entry for querying
|
||||
-- snapshot data
|
||||
--
|
||||
-- TODO: update the snapshot row with snapshot end sysdate too
|
||||
-- or put the number of milliseconds spent taking the snapshot
|
||||
|
||||
select sawr$snapid_seq.nextval into l_snapid from dual;
|
||||
insert into sawr$snapshots values ( l_snapid, sysdate, user, g_snap_mode, l_snap_comment );
|
||||
|
||||
return l_snapid;
|
||||
else
|
||||
return p_snapid;
|
||||
end if;
|
||||
end assign_snapid;
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- FUNCTION: in_list
|
||||
-- PURPOSE: generic function for returning a collection of numbers from the dynamic query
|
||||
-- passed in p_sql parameter.
|
||||
-- for example, it's used for getting list of SIDs based on dynamic query
|
||||
-- against v$session
|
||||
-- PARAMETERS:
|
||||
-- p_sql : SQL text string which should return a list of session IDs (in number format)
|
||||
-- : no restriction where and how the list of SIDs is retrieved, such SIDs should
|
||||
-- : just exist in V$SESSION, otherwise nothing is sampled
|
||||
-- : for example, value can be 'select sid from v$session where username = '''APPS''''
|
||||
-- : or 'select sid from v$session where status = '''ACTIVE''' and last_call_et > 5'
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
function in_list( p_sql in varchar2 ) return sawr$SIDlist
|
||||
as
|
||||
type rc is ref cursor;
|
||||
l_cursor rc;
|
||||
l_tmp number;
|
||||
l_data sawr$sidlist := sawr$SIDlist();
|
||||
|
||||
begin
|
||||
open l_cursor for p_sql;
|
||||
loop
|
||||
|
||||
fetch l_cursor into l_tmp;
|
||||
exit when l_cursor%notfound;
|
||||
l_data.extend;
|
||||
l_data(l_data.count) := l_tmp;
|
||||
|
||||
end loop;
|
||||
close l_cursor;
|
||||
|
||||
return l_data;
|
||||
end in_list; -- ( p_sql in varchar2 )
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- FUNCTION: valid_stat_modes
|
||||
-- PURPOSE: Function for returning a collection of valid snap modes as determined by
|
||||
-- the sawr$session_stat_mode table.
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
function valid_stat_modes return sawr$ModeList is
|
||||
l_modes sawr$ModeList;
|
||||
begin
|
||||
select distinct upper(mode_id) bulk collect into l_modes
|
||||
from sawr$session_stat_mode;
|
||||
return l_modes;
|
||||
end valid_stat_modes;
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- FUNCTION: snap_sidlist_internal (overloaded, p_sidlist as sawr$SIDlist type)
|
||||
--
|
||||
-- PURPOSE: this is the low-level procedure doing the actual sampling from V$ views
|
||||
-- and inserting the result to SAWR$ tables
|
||||
--
|
||||
-- PARAMETERS:
|
||||
-- p_sidlist : sawr$SIDlist collection, this is array of SIDs to be sampled from V$SESSION
|
||||
-- p_snapid : snapshot ID to be inserted into SAWR$ tables. normally this comes from
|
||||
-- parent functions, but is autogenerated when the low-level function is
|
||||
-- executed manually and by leaving p_snapid as NULL.
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_sidlist_internal( p_sidlist in sawr$SIDlist, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null)
|
||||
as
|
||||
l_snapid number;
|
||||
l_codeloc varchar2(200) := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): BEGIN';
|
||||
begin
|
||||
|
||||
-- this variable is here for easier catching of exception sources in pre-10g dbs
|
||||
l_codeloc:= 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): CALL ASSIGN_SNAPID';
|
||||
|
||||
-- allocate a new snapid if a global one hasn't been passed down from caller
|
||||
-- new snapid allocation inserts a line to SAWR$SNAPSHOTS table
|
||||
l_snapid := assign_snapid(p_snapid);
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- insert sessions matching parameter conditions into SAWR$SESSIONS table
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSIONS';
|
||||
insert into
|
||||
sawr$sessions (
|
||||
snapid
|
||||
, snaptime
|
||||
, program
|
||||
, username
|
||||
, machine
|
||||
, osuser
|
||||
, terminal
|
||||
, module
|
||||
, action
|
||||
, audsid
|
||||
, sid
|
||||
, serial#
|
||||
, process
|
||||
, logon_time
|
||||
)
|
||||
select
|
||||
l_snapid
|
||||
, sysdate as snaptime
|
||||
, nvl(s.program , '-')
|
||||
, nvl(s.username , '-')
|
||||
, nvl(s.machine , '-')
|
||||
, nvl(s.osuser , '-')
|
||||
, nvl(s.terminal , '-')
|
||||
, nvl(module , '-')
|
||||
, nvl(action , '-')
|
||||
, s.audsid
|
||||
, s.sid
|
||||
, s.serial#
|
||||
, s.process
|
||||
, s.logon_time
|
||||
from
|
||||
v$session s
|
||||
where
|
||||
sid in (
|
||||
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- insert matching session wait events into SAWR$SESSION_EVENTS table
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSION_EVENTS';
|
||||
insert into
|
||||
sawr$session_events (
|
||||
snapid
|
||||
, snaptime
|
||||
, audsid
|
||||
, sid
|
||||
, serial#
|
||||
, event#
|
||||
, total_waits
|
||||
, total_timeouts
|
||||
, average_wait
|
||||
, max_wait
|
||||
, time_waited_micro
|
||||
)
|
||||
select --+ ORDERED tanel9
|
||||
l_snapid,
|
||||
sysdate as snaptime,
|
||||
s.audsid,
|
||||
e.sid,
|
||||
s.serial#,
|
||||
en.event#,
|
||||
e.total_waits,
|
||||
e.total_timeouts,
|
||||
e.average_wait,
|
||||
e.max_wait,
|
||||
-- e.time_waited_micro + ( decode(e.event||w.state, w.event||'WAITING', w.seconds_in_wait, 0) * 1000000 ) time_waited_micro
|
||||
e.time_waited_micro + NVL( CASE e.event||w.state
|
||||
WHEN w.event||'WAITING' THEN
|
||||
CASE
|
||||
WHEN w.event IN ( select event from v$system_event where total_timeouts != 0 ) THEN 0
|
||||
ELSE w.seconds_in_wait
|
||||
END
|
||||
ELSE 0
|
||||
END
|
||||
* 1000000, 0 ) time_waited_micro
|
||||
|
||||
from
|
||||
v$session s,
|
||||
v$session_event e,
|
||||
v$session_wait w,
|
||||
v$event_name en
|
||||
where
|
||||
e.sid = s.sid
|
||||
and s.sid = w.sid
|
||||
and w.sid = e.sid
|
||||
and e.event = en.name
|
||||
and s.sid in (
|
||||
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
|
||||
);
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- insert used CPU time to session events table as well
|
||||
-- in 9i V$SESSTAT (CPU used by this session) is used
|
||||
-- from 10g V$SESS_TIME_MODEL is used as this is more accurate and is updated every 5 seconds
|
||||
-- even during database CALL
|
||||
--
|
||||
-- note that the installer script automatically comments out the irrelevant part depending on db version
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- the line below is substituted by "/*" by sqlplus during installation onto 9i database
|
||||
&version_9_enable
|
||||
|
||||
-- 9i version for getting session CPU usage
|
||||
insert into
|
||||
sawr$session_events (
|
||||
snapid
|
||||
, snaptime
|
||||
, audsid
|
||||
, sid
|
||||
, serial#
|
||||
, event#
|
||||
, total_waits
|
||||
, time_waited_micro
|
||||
)
|
||||
select --+ ORDERED USE_NL(s st)
|
||||
l_snapid,
|
||||
sysdate as snaptime,
|
||||
s.audsid,
|
||||
s.sid,
|
||||
s.serial#,
|
||||
-1, -- naming CPU usage as event# -1
|
||||
1, -- setting total waits for CPU to 1 for now (this can be got from perhaps number of calls or sum(events) later on)
|
||||
st.value * 10000 -- x10000 makes microseconds out of centiseconds
|
||||
from
|
||||
v$session s,
|
||||
v$sesstat st
|
||||
where
|
||||
st.statistic# = (select statistic# from v$statname where name = 'CPU used by this session')
|
||||
and s.sid = st.sid
|
||||
and s.sid in (
|
||||
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
|
||||
);
|
||||
|
||||
-- end: version_9_enable
|
||||
-- */
|
||||
|
||||
-- the line below is substituted by "/*" by sqlplus during installation onto 10g and above database
|
||||
&version_10_enable
|
||||
|
||||
-- 10g+ version for getting session CPU usage
|
||||
insert into
|
||||
sawr$session_events (
|
||||
snapid
|
||||
, snaptime
|
||||
, audsid
|
||||
, sid
|
||||
, serial#
|
||||
, event#
|
||||
, total_waits
|
||||
, time_waited_micro
|
||||
)
|
||||
select --+ ORDERED USE_NL(s st)
|
||||
l_snapid,
|
||||
sysdate as snaptime,
|
||||
s.audsid,
|
||||
s.sid,
|
||||
s.serial#,
|
||||
-1, -- naming CPU usage as event# -1
|
||||
1, -- setting total waits for CPU to 1 for now (this can be got from perhaps number of calls or sum(events) later on)
|
||||
st.value -- v$sess_time_model reports times in microseconds
|
||||
from
|
||||
v$session s,
|
||||
v$sess_time_model st
|
||||
where
|
||||
st.stat_name = 'DB CPU'
|
||||
and s.sid = st.sid
|
||||
and s.sid in (
|
||||
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
|
||||
);
|
||||
|
||||
-- end: version_10_enable
|
||||
-- */
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- insert matching session statistics into SAWR$SESSION_STATS table
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSION_STATS';
|
||||
insert into
|
||||
sawr$session_stats (
|
||||
snapid
|
||||
, snaptime
|
||||
, audsid
|
||||
, sid
|
||||
, serial#
|
||||
, statistic#
|
||||
, value
|
||||
)
|
||||
select --+ ORDERED USE_NL(s ss) INDEX(s) tanel2
|
||||
l_snapid,
|
||||
sysdate as snaptime,
|
||||
s.audsid,
|
||||
s.sid,
|
||||
s.serial#,
|
||||
ss.statistic#,
|
||||
ss.value
|
||||
from
|
||||
v$session s,
|
||||
v$sesstat ss
|
||||
where
|
||||
s.sid = ss.sid
|
||||
and s.sid in (
|
||||
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
|
||||
)
|
||||
and ss.statistic# in (
|
||||
select --+ ORDERED NO_UNNEST
|
||||
statistic#
|
||||
from
|
||||
sawr$session_stat_mode cfg,
|
||||
v$statname sn
|
||||
where
|
||||
sn.name = cfg.statistic_name
|
||||
and cfg.mode_id = p_session_stats
|
||||
)
|
||||
and ss.value != 0;
|
||||
|
||||
|
||||
|
||||
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): END';
|
||||
|
||||
exception
|
||||
when NO_DATA_FOUND then null; -- its ok to find no matches for snapshot query
|
||||
when others then raise_application_error(-20001, 'Error '||SQLCODE||': '||SQLERRM||' : FAILED AT '|| l_codeloc) ;
|
||||
|
||||
|
||||
end snap_sidlist_internal; -- ( p_sidlist in sawr$SIDlist )
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- FUNCTION: snap_sidlist_internal (overloaded, p_sidlist as VARCHAR2 type)
|
||||
--
|
||||
-- PURPOSE: this is a procedure accepting any SQL which returns array of
|
||||
-- SIDs (NUMBER format) which are then used for calling the
|
||||
-- snap_sidlist_internal sister function to extract session info
|
||||
-- from V$SESSION
|
||||
--
|
||||
-- PARAMETERS:
|
||||
-- p_sidlist : sawr$SIDlist collection, this is array of SIDs to be sampled from V$SESSION
|
||||
-- p_snapid : snapshot ID to be inserted into SAWR$ tables. normally this comes from
|
||||
-- parent functions, but is autogenerated when the low-level function is
|
||||
-- executed manually and by leaving p_snapid as NULL.
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_sidlist_internal(p_sql in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null)
|
||||
is
|
||||
l_snapid number;
|
||||
begin
|
||||
|
||||
-- allocate a new snapid if a global one hasn't been passed down from caller
|
||||
l_snapid := assign_snapid(p_snapid);
|
||||
|
||||
-- call the overloaded snap_sidlist_internal sister-function
|
||||
-- which accepts sawr$SIDlist collection as a parameter
|
||||
snap_sidlist_internal( in_list(p_sql), p_session_stats, l_snapid );
|
||||
|
||||
end snap_sidlist_internal; -- ( p_sql in varchar2 )
|
||||
|
||||
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
--
|
||||
-- External Procs to be executed by users
|
||||
--
|
||||
--==================================================================================================================
|
||||
--==================================================================================================================
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping current session
|
||||
-- useful for ad-hoc instrumentation and performance diagnosis for SQL tuning
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_me(p_session_stats in varchar2 default 'ALL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_ME: '||user;
|
||||
snap_sidlist_internal( 'select sid from v$mystat where rownum = 1', p_session_stats );
|
||||
commit;
|
||||
end snap_me;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap session with given SID
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_sid ( p_sid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_SID: '||to_char(p_sid);
|
||||
snap_sidlist_internal( 'select sid from v$session where sid in ('||to_char(p_sid)||')' , p_session_stats );
|
||||
commit;
|
||||
end snap_sid;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap session with given SID
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_sid ( p_sid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_SID: '||p_sid;
|
||||
snap_sidlist_internal( 'select sid from v$session where sid in ('||p_sid||')' , p_session_stats );
|
||||
commit;
|
||||
end snap_sid;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping all sessions
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_all(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_ALL:';
|
||||
snap_sidlist_internal( 'select sid from v$session' , p_session_stats );
|
||||
commit;
|
||||
end snap_all;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping all BACKGROUND sessions
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_bg(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_BG:';
|
||||
snap_sidlist_internal( 'select sid from v$session where type = ''BACKGROUND''' , p_session_stats );
|
||||
commit;
|
||||
end snap_bg;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping all USER sessions
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_fg(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_FG:';
|
||||
snap_sidlist_internal( 'select sid from v$session where type = ''USER''' , p_session_stats );
|
||||
commit;
|
||||
end snap_fg;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping all sessions estabilished by specified Oracle user
|
||||
-- default value null will snap all sessions by current user
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_orauser(p_username in varchar2 default user, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_ORAUSER: '||p_username;
|
||||
snap_sidlist_internal('select sid from v$session where username like '''|| p_username ||'''' , p_session_stats );
|
||||
commit;
|
||||
end snap_orauser;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- procedure for snapping all sessions estabilished by specified OS user
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_osuser(p_username in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_OSUSER: '||p_username;
|
||||
snap_sidlist_internal('select sid from v$session where osuser like '''|| p_username ||'''' , p_session_stats );
|
||||
commit;
|
||||
end snap_osuser;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap all sessions by program name (v$session.program)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_program( p_program in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_PROGRAM: '||p_program;
|
||||
snap_sidlist_internal('select sid from v$session where program like '''|| p_program ||'''' , p_session_stats );
|
||||
commit;
|
||||
end snap_program;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap all sessions by terminal (v$session.terminal)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_terminal( p_terminal in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_TERMINAL: '||p_terminal;
|
||||
snap_sidlist_internal('select sid from v$session where terminal like '''|| p_terminal ||'''' , p_session_stats );
|
||||
commit;
|
||||
end snap_terminal;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap all sessions by machine (v$session.machine)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_machine( p_machine in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_MACHINE: '||p_machine;
|
||||
snap_sidlist_internal('select sid from v$session where machine like '''|| p_machine ||'''' , p_session_stats);
|
||||
commit;
|
||||
end snap_machine;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap the session being served by SPID (v$process.spid)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_spid( p_spid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_CPID: '||p_spid;
|
||||
snap_sidlist_internal('select sid from v$session where paddr in ( select addr from v$process where spid in ('''|| p_spid ||'''))' , p_session_stats );
|
||||
commit;
|
||||
end snap_spid;
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap the session being served by SPID (v$process.spid)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_spid( p_spid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_CPID: '||p_spid;
|
||||
snap_sidlist_internal('select sid from v$session where paddr in ( select addr from v$process where spid in ('''|| to_char(p_spid) ||'''))' , p_session_stats );
|
||||
commit;
|
||||
end snap_spid;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap all sessions by client PID (v$session.process)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_cpid( p_cpid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_CPID: '||p_cpid;
|
||||
snap_sidlist_internal('select sid from v$session where process in ('''|| p_cpid ||''')' , p_session_stats );
|
||||
commit;
|
||||
end snap_cpid;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- snap all sessions by client PID (v$session.process)
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure snap_cpid( p_cpid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
|
||||
pragma autonomous_transaction;
|
||||
begin
|
||||
g_snap_mode:='SNAP_CPID: '||to_char(p_cpid);
|
||||
snap_sidlist_internal('select sid from v$session where process in ('''|| to_char(p_cpid) ||''')' , p_session_stats );
|
||||
commit;
|
||||
end snap_cpid;
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
-- purge repository data over a certain age threshold
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
procedure purge_data ( p_days_threshold in number default 7, p_snapid in number default null ) is
|
||||
|
||||
type sawr$TableList is table of varchar2(30);
|
||||
l_tables sawr$TableList := sawr$TableList('SAWR$SNAPSHOTS',
|
||||
'SAWR$SESSIONS',
|
||||
'SAWR$SESSION_EVENTS',
|
||||
'SAWR$SESSION_STATS');
|
||||
|
||||
l_snaptime date := trunc(sysdate)-nvl(p_days_threshold,7);
|
||||
l_codeloc varchar2(200) := 'PURGE_DATA: BEGIN';
|
||||
l_ddl varchar2(200);
|
||||
|
||||
pragma autonomous_transaction;
|
||||
|
||||
begin
|
||||
|
||||
l_codeloc := 'PURGE_DATA: DELETE DATA';
|
||||
for i in 1 .. l_tables.count loop
|
||||
l_codeloc := 'PURGE_DATA: DELETE ' || l_tables(i);
|
||||
execute immediate ' delete from ' || l_tables(i) ||
|
||||
' where snaptime < :snaptime ' ||
|
||||
' and (snapid = :snapid or :snapid is null)'
|
||||
using l_snaptime, p_snapid, p_snapid;
|
||||
end loop;
|
||||
|
||||
l_codeloc := 'PURGE_DATA: REBUILD_TABLES';
|
||||
for i in 1 .. l_tables.count loop
|
||||
|
||||
l_ddl := case l_tables(i)
|
||||
when 'SAWR$SNAPSHOTS'
|
||||
then 'alter index SAWR$SNAPSHOTS_PK coalesce'
|
||||
else 'alter table ' || l_tables(i) || ' move online'
|
||||
end;
|
||||
l_codeloc := 'PURGE_DATA: REBUILD ' || l_tables(i);
|
||||
execute immediate l_ddl;
|
||||
end loop;
|
||||
|
||||
l_codeloc := 'PURGE_DATA: END';
|
||||
|
||||
exception
|
||||
when others then
|
||||
raise_application_error(-20001, 'Error '||SQLCODE||': '||SQLERRM||' : FAILED AT '|| l_codeloc) ;
|
||||
end purge_data;
|
||||
|
||||
end sesspack;
|
||||
/
|
||||
|
||||
show errors
|
||||
|
||||
|
||||
|
||||
249
tpt/tools/sesspack_0.05_release/install_sesspack_schema.sql
Normal file
249
tpt/tools/sesspack_0.05_release/install_sesspack_schema.sql
Normal file
@@ -0,0 +1,249 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
create or replace type sawr$SIDList is table of number;
|
||||
/
|
||||
|
||||
create or replace type sawr$ModeList is table of varchar2(30);
|
||||
/
|
||||
|
||||
create sequence sawr$snapid_seq cache 10 order;
|
||||
|
||||
create table sawr$snapshots (
|
||||
snapid number,
|
||||
snaptime date not null,
|
||||
takenby varchar2(100) default user not null,
|
||||
snap_mode varchar2(100) not null,
|
||||
snap_comment varchar2(4000)
|
||||
);
|
||||
create index sawr$snapshots_pk on sawr$snapshots ( snapid, snaptime );
|
||||
alter table sawr$snapshots add constraint sawr$snapshots_pk primary key (snapid) using index sawr$snapshots_pk;
|
||||
|
||||
create table sawr$sessions (
|
||||
snapid number not null
|
||||
, snaptime date not null
|
||||
, program varchar2(48) not null
|
||||
, module varchar2(48) not null
|
||||
, action varchar2(32) not null
|
||||
, username varchar2(30) not null
|
||||
, machine varchar2(64) not null
|
||||
, osuser varchar2(30) not null
|
||||
, terminal varchar2(30) not null
|
||||
, audsid number not null
|
||||
, sid number not null
|
||||
, serial# number not null
|
||||
, process varchar2(12)
|
||||
, logon_time date
|
||||
, sql_hash_value number
|
||||
, prev_hash_value number
|
||||
, client_info varchar2(64)
|
||||
, row_wait_obj# number
|
||||
, row_wait_file# number
|
||||
, row_wait_block# number
|
||||
, row_wait_row# number
|
||||
, last_call_et number
|
||||
, client_identifier varchar2(64)
|
||||
, constraint sawr$sessions_pk primary key (
|
||||
snapid
|
||||
, snaptime
|
||||
, program
|
||||
, module
|
||||
, action
|
||||
, username
|
||||
, machine
|
||||
, osuser
|
||||
, terminal
|
||||
, sid
|
||||
, serial#
|
||||
, audsid
|
||||
) -- so many PK columns and such column order is used for achieving good compressed IOT storage
|
||||
)
|
||||
organization index compress;
|
||||
|
||||
create table sawr$session_events (
|
||||
snapid number
|
||||
, snaptime date
|
||||
, audsid number
|
||||
, sid number
|
||||
, serial# number
|
||||
, event# number
|
||||
, total_timeouts number
|
||||
, total_waits number
|
||||
, average_wait number
|
||||
, max_wait number
|
||||
, time_waited_micro number
|
||||
, event_id number
|
||||
, constraint sawr$session_events_pk primary key (
|
||||
snapid,
|
||||
snaptime,
|
||||
audsid,
|
||||
sid,
|
||||
serial#,
|
||||
event#
|
||||
)
|
||||
)
|
||||
organization index compress;
|
||||
|
||||
create table sawr$session_stats (
|
||||
snapid number
|
||||
, snaptime date
|
||||
, audsid number
|
||||
, sid number
|
||||
, serial# number
|
||||
, statistic# number
|
||||
, value number
|
||||
, constraint sawr$session_stats_pk primary key (
|
||||
snapid,
|
||||
snaptime,
|
||||
audsid,
|
||||
sid,
|
||||
serial#,
|
||||
statistic#
|
||||
)
|
||||
)
|
||||
organization index compress;
|
||||
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
-- Table for V$SESSTAT sampling templates
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
create table sawr$session_stat_mode (
|
||||
mode_id varchar(30) not null,
|
||||
statistic_name varchar2(250) not null,
|
||||
constraint sawr$session_stat_mode_pk primary key (mode_id, statistic_name)
|
||||
)
|
||||
organization index;
|
||||
|
||||
insert into sawr$session_stat_mode
|
||||
select
|
||||
'MINIMAL',
|
||||
name
|
||||
from
|
||||
v$statname
|
||||
where
|
||||
name in (
|
||||
'user calls',
|
||||
'user commits'
|
||||
)
|
||||
/
|
||||
|
||||
insert into sawr$session_stat_mode
|
||||
select
|
||||
'TYPICAL',
|
||||
name
|
||||
from
|
||||
v$statname
|
||||
where
|
||||
name in (
|
||||
'user calls',
|
||||
'user commits',
|
||||
'parse count (total)',
|
||||
'parse count (hard)',
|
||||
'execute count',
|
||||
'consistent gets',
|
||||
'db block gets'
|
||||
)
|
||||
/
|
||||
|
||||
insert into sawr$session_stat_mode
|
||||
select
|
||||
'DETAILED',
|
||||
name
|
||||
from
|
||||
v$statname
|
||||
where
|
||||
name in (
|
||||
'user calls',
|
||||
'user commits',
|
||||
'parse count (total)',
|
||||
'parse count (hard)',
|
||||
'execute count',
|
||||
'consistent gets',
|
||||
'consistent gets - examination',
|
||||
'db block gets',
|
||||
'parse time cpu',
|
||||
'parse time elapsed',
|
||||
'sorts (memory)',
|
||||
'sorts (disk)',
|
||||
'sorts (rows)',
|
||||
'transaction rollbacks',
|
||||
'user rollbacks'
|
||||
)
|
||||
/
|
||||
|
||||
insert into sawr$session_stat_mode
|
||||
select
|
||||
'ALL',
|
||||
name
|
||||
from
|
||||
v$statname
|
||||
/
|
||||
|
||||
|
||||
commit;
|
||||
|
||||
|
||||
-- SAWR$SESS_EVENT
|
||||
-- View consolidating sessions events and values over taken snapshots
|
||||
|
||||
create or replace view sawr$sess_event as
|
||||
select
|
||||
snap.snapid, snap.snaptime,
|
||||
s.sid, s.audsid, s.serial#,
|
||||
s.username, s.program, s.terminal, s.machine,
|
||||
s.osuser, s.process, s.module, s.action,
|
||||
en.event#, en.name, e.time_waited_micro,
|
||||
e.total_waits, e.average_wait, s.logon_time
|
||||
from
|
||||
sawr$snapshots snap,
|
||||
sawr$sessions s,
|
||||
sawr$session_events e,
|
||||
( select event#, name from v$event_name
|
||||
union all
|
||||
select -1, 'CPU Usage' from dual
|
||||
) en
|
||||
where
|
||||
snap.snapid = s.snapid
|
||||
and snap.snapid = e.snapid
|
||||
and s.audsid = e.audsid
|
||||
and s.sid = e.sid
|
||||
and s.serial# = e.serial#
|
||||
and en.event# = e.event#
|
||||
/
|
||||
|
||||
-- SAWR$SESS_STAT
|
||||
-- View consolidating sessions stats and values over taken snapshots
|
||||
|
||||
create or replace view sawr$sess_stat as
|
||||
select
|
||||
snap.snapid, snap.snaptime,
|
||||
s.sid, s.audsid, s.serial#,
|
||||
s.username, s.program, s.terminal, s.machine,
|
||||
s.osuser, s.process, s.module, s.action,
|
||||
sn.statistic#, sn.name, ss.value, s.logon_time
|
||||
from
|
||||
sawr$snapshots snap,
|
||||
sawr$sessions s,
|
||||
sawr$session_stats ss,
|
||||
v$statname sn
|
||||
where
|
||||
snap.snapid = s.snapid
|
||||
and snap.snapid = ss.snapid
|
||||
and s.audsid = ss.audsid
|
||||
and s.sid = ss.sid
|
||||
and s.serial# = ss.serial#
|
||||
and sn.statistic# = ss.statistic#
|
||||
/
|
||||
|
||||
|
||||
40
tpt/tools/sesspack_0.05_release/list.sql
Normal file
40
tpt/tools/sesspack_0.05_release/list.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
set lines 156
|
||||
|
||||
column sawr_list_takenby heading "Taken By" format a20
|
||||
column sawr_list_snapid heading "Snap ID" format 9999999
|
||||
column sawr_list_snaptime heading "Snapshot Time" format a20
|
||||
column sawr_session_count heading "Snapped|Sessions" format 9999999
|
||||
column sawr_snap_mode heading "Snapshot|Mode" format a40
|
||||
|
||||
select
|
||||
snap.snapid sawr_list_snapid,
|
||||
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS') sawr_list_snaptime,
|
||||
snap.takenby sawr_list_takenby,
|
||||
snap.snap_mode sawr_snap_mode,
|
||||
count(*) sawr_session_count
|
||||
from
|
||||
sawr$snapshots snap,
|
||||
sawr$sessions sess
|
||||
where
|
||||
snap.snapid = sess.snapid
|
||||
group by
|
||||
snap.snapid,
|
||||
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS'),
|
||||
snap.snap_mode,
|
||||
snap.takenby
|
||||
order by
|
||||
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS')
|
||||
/
|
||||
167
tpt/tools/sesspack_0.05_release/old_sr.sql
Normal file
167
tpt/tools/sesspack_0.05_release/old_sr.sql
Normal file
@@ -0,0 +1,167 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
set feedback off null "[NULL]"
|
||||
|
||||
-- define _tptmode = normal
|
||||
define grouping=&1
|
||||
define start_snap=&2
|
||||
define end_snap=&3
|
||||
|
||||
col wait_ms for 9999999999
|
||||
col avg_wait_ms for 99999999.9
|
||||
col ms_per_sec for 999999.9
|
||||
|
||||
col program for a30 truncate
|
||||
col username for a15 truncate
|
||||
col osuser for a20 truncate
|
||||
col name for a30 truncate
|
||||
col machine for a20 truncate
|
||||
|
||||
col grouping_break noprint new_value grouping_break
|
||||
--set termout off
|
||||
select replace('&grouping', ',', ' on ') grouping_break from dual;
|
||||
--set termout on
|
||||
|
||||
break on &grouping_break skip 1
|
||||
|
||||
|
||||
select
|
||||
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
|
||||
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
|
||||
(b.snaptime - a.snaptime)*86400 dur_sec,
|
||||
(b.snaptime - a.snaptime)*86400/60 dur_min
|
||||
from
|
||||
(select snaptime from sawr$snapshots where snapid = &2) a,
|
||||
(select snaptime from sawr$snapshots where snapid = &3) b
|
||||
/
|
||||
|
||||
|
||||
select
|
||||
&grouping,
|
||||
substr(name,1,45) name,
|
||||
decode(lower('&_tptmode'),'html','','|')||
|
||||
rpad(
|
||||
nvl(
|
||||
lpad('#',
|
||||
ceil( (nvl(round(sum(us_per_sec/1000000),2),0))*10 ),
|
||||
'#'),
|
||||
' '),
|
||||
10,' ')
|
||||
||decode(lower('&_tptmode'),'html','','|') "%Total",
|
||||
sum(us_per_sec)/1000 ms_per_sec,
|
||||
(sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) avg_wait_ms,
|
||||
sum(waits) waits,
|
||||
sum(wait_us)/1000 wait_ms
|
||||
-- ,avg(intrvl)/1000 sec_in_snap
|
||||
from (
|
||||
select
|
||||
e2.sid,
|
||||
e2.audsid,
|
||||
nvl(e1.snapid, &start_snap) begin_snapid,
|
||||
e2.snapid end_snapid,
|
||||
e2.username,
|
||||
e2.program,
|
||||
e2.terminal,
|
||||
e2.machine,
|
||||
e2.osuser,
|
||||
e2.module,
|
||||
e2.action,
|
||||
e2.name,
|
||||
round(e2.time_waited_micro - nvl(e1.time_waited_micro,0)) wait_us,
|
||||
round(
|
||||
( e2.time_waited_micro - nvl(e1.time_waited_micro,0) ) / (
|
||||
decode((e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400, 0, 1,
|
||||
(e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400)
|
||||
)
|
||||
) us_per_sec,
|
||||
(e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400*1000 intrvl,
|
||||
e2.total_waits - nvl(e1.total_waits,0) waits
|
||||
-- e1.average_wait avg1,
|
||||
-- e2.average_wait avg2,
|
||||
-- e2.average_wait - nvl(e1.average_wait,0) avgdelta
|
||||
from
|
||||
( select * from sawr$sess_event where snapid = &start_snap ) e1,
|
||||
( select * from sawr$sess_event where snapid = &end_snap ) e2
|
||||
where
|
||||
e1.audsid (+) = e2.audsid
|
||||
and e1.sid (+) = e2.sid
|
||||
and e1.serial# (+) = e2.serial#
|
||||
and e1.logon_time (+) = e2.logon_time
|
||||
and e1.event# (+) = e2.event#
|
||||
) sq
|
||||
where
|
||||
( waits != 0 or wait_us != 0 )
|
||||
group by
|
||||
&grouping, name
|
||||
order by
|
||||
&grouping, ms_per_sec desc
|
||||
/
|
||||
|
||||
col delta head Delta for 9999999999
|
||||
col delta_sec head D/sec for 9999999.9
|
||||
|
||||
select
|
||||
&grouping,
|
||||
substr(name,1,45) name,
|
||||
decode(lower('&_tptmode'),'html','','|')||
|
||||
rpad(
|
||||
nvl(
|
||||
lpad('#',
|
||||
ceil( nvl(log(10,abs(decode(sum(delta),0,1,sum(delta)))),0) ),
|
||||
'#'),
|
||||
' '),
|
||||
10,' ')
|
||||
||decode(lower('&_tptmode'),'html','','|') "log10(D)",
|
||||
sum(delta) delta,
|
||||
sum(delta)/(avg(intrvl)/1000) delta_sec
|
||||
-- ,avg(intrvl)/1000 sec_in_snap
|
||||
from (
|
||||
select
|
||||
s2.sid,
|
||||
s2.audsid,
|
||||
nvl(s1.snapid, &start_snap) begin_snapid,
|
||||
s2.snapid end_snapid,
|
||||
s2.username,
|
||||
s2.program,
|
||||
s2.terminal,
|
||||
s2.machine,
|
||||
s2.osuser,
|
||||
s2.process,
|
||||
s2.name,
|
||||
s2.module,
|
||||
s2.action,
|
||||
s2.value - nvl(s1.value,0) delta,
|
||||
(s2.snaptime - nvl(s1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400*1000 intrvl
|
||||
from
|
||||
( select * from sawr$sess_stat where snapid = &start_snap ) s1,
|
||||
( select * from sawr$sess_stat where snapid = &end_snap ) s2
|
||||
where
|
||||
s1.audsid (+) = s2.audsid
|
||||
and s1.sid (+) = s2.sid
|
||||
and s1.serial# (+) = s2.serial#
|
||||
and s1.logon_time (+) = s2.logon_time
|
||||
and s1.statistic# (+) = s2.statistic#
|
||||
) sq
|
||||
where
|
||||
delta != 0
|
||||
group by
|
||||
&grouping, name
|
||||
order by
|
||||
&grouping, abs(delta) desc
|
||||
/
|
||||
|
||||
|
||||
break on _nonexistent
|
||||
set feedback on null ""
|
||||
61
tpt/tools/sesspack_0.05_release/prepare_user.sql
Normal file
61
tpt/tools/sesspack_0.05_release/prepare_user.sql
Normal file
@@ -0,0 +1,61 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- whenever sqlerror exit 1 rollback
|
||||
set verify off
|
||||
|
||||
-- create sesspack roles
|
||||
create role sesspack_user_role;
|
||||
create role sesspack_admin_role;
|
||||
|
||||
-- grant the roles to sesspack schema holder
|
||||
grant sesspack_user_role to &spuser with admin option;
|
||||
grant sesspack_user_role to sesspack_admin_role;
|
||||
grant sesspack_admin_role to &spuser with admin option;
|
||||
|
||||
-- two additional privs to sesspack owner to avoid ORA-01720
|
||||
grant select on sys.v_$event_name to &spuser with grant option;
|
||||
grant select on sys.v_$statname to &spuser with grant option;
|
||||
|
||||
-- grant privs required for taking and scheduling snapshots
|
||||
grant select on sys.v_$mystat to sesspack_user_role;
|
||||
grant select on sys.v_$session to sesspack_user_role;
|
||||
grant select on sys.v_$session_wait to sesspack_user_role;
|
||||
grant select on sys.v_$session_event to sesspack_user_role;
|
||||
grant select on sys.v_$system_event to sesspack_user_role;
|
||||
grant select on sys.v_$sess_time_model to sesspack_user_role;
|
||||
grant select on sys.v_$sesstat to sesspack_user_role;
|
||||
grant select on sys.v_$event_name to sesspack_user_role;
|
||||
grant select on sys.v_$statname to sesspack_user_role;
|
||||
grant execute on sys.dbms_job to &spuser;
|
||||
-- for 10g
|
||||
grant create job to &spuser;
|
||||
|
||||
grant create table to &spuser;
|
||||
grant create view to &spuser;
|
||||
grant create type to &spuser;
|
||||
grant create procedure to &spuser;
|
||||
grant create public synonym to &spuser;
|
||||
|
||||
grant select on sys.v_$mystat to &spuser;
|
||||
grant select on sys.v_$session to &spuser;
|
||||
grant select on sys.v_$session_wait to &spuser;
|
||||
grant select on sys.v_$session_event to &spuser;
|
||||
grant select on sys.v_$system_event to &spuser;
|
||||
grant select on sys.v_$sess_time_model to &spuser;
|
||||
grant select on sys.v_$sesstat to &spuser;
|
||||
grant select on sys.v_$event_name to &spuser;
|
||||
grant select on sys.v_$statname to &spuser;
|
||||
|
||||
set verify on
|
||||
whenever sqlerror continue
|
||||
59
tpt/tools/sesspack_0.05_release/reinst.sql
Normal file
59
tpt/tools/sesspack_0.05_release/reinst.sql
Normal file
@@ -0,0 +1,59 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
define spuser=perfstat
|
||||
define sphost=ora92
|
||||
define sppass=oracle
|
||||
define sysuser=sys
|
||||
define syspass=oracle
|
||||
|
||||
connect &spuser/&sppass@&sphost
|
||||
|
||||
column sesspack_v9 noprint new_value version_9_enable
|
||||
column sesspack_v10 noprint new_value version_10_enable
|
||||
|
||||
with SQ as (
|
||||
select substr(
|
||||
substr(banner, instr(banner, 'Release ')+8),
|
||||
1,
|
||||
instr(substr(banner, instr(banner, 'Release ')+8),'.')-1
|
||||
) db_version
|
||||
from v$version
|
||||
where rownum = 1
|
||||
)
|
||||
select
|
||||
case when db_version = '9' then '--' else '/*' end sesspack_v9,
|
||||
case when db_version = '10' then '--' else '/*' end sesspack_v10
|
||||
from sq;
|
||||
|
||||
|
||||
|
||||
prompt Uninstalling schema...
|
||||
|
||||
|
||||
@@drop_sesspack_packages.sql
|
||||
@@drop_sesspack_schema.sql
|
||||
|
||||
--connect &sysuser/&syspass@&sphost
|
||||
|
||||
-- @@prepare_user.sql
|
||||
|
||||
-- connect &spuser/oracle
|
||||
|
||||
prompt Installing schema...
|
||||
|
||||
@@install_sesspack_schema.sql
|
||||
@@install_sesspack_packages.sql
|
||||
@@install_grants_syns.sql
|
||||
|
||||
-- connect / as sysdba
|
||||
15
tpt/tools/sesspack_0.05_release/reinstall_sesspack.sql
Normal file
15
tpt/tools/sesspack_0.05_release/reinstall_sesspack.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@drop_sesspack.sql
|
||||
@@install_sesspack.sql
|
||||
10
tpt/tools/sesspack_0.05_release/sesspack_ps.sh
Normal file
10
tpt/tools/sesspack_0.05_release/sesspack_ps.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Note that this is currently only for Solaris
|
||||
|
||||
while true
|
||||
do
|
||||
echo `date +%Y%m%d%H%M%S`";"BEGIN_PS_SAMPLE > /tmp/sawr_ps_pipe
|
||||
ps -u oracle -o pid,time | awk '{ if ( NR > 1 ) print $1";"$2 }' > /tmp/sawr_ps_pipe
|
||||
done
|
||||
|
||||
38
tpt/tools/sesspack_0.05_release/sesspack_purge.sql
Normal file
38
tpt/tools/sesspack_0.05_release/sesspack_purge.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
define spuser=&1
|
||||
define spkeep=&2
|
||||
|
||||
prompt
|
||||
|
||||
set heading off feedback off
|
||||
select 'sesspack_purge: removing records older than '|| to_char( sysdate - &spkeep, 'YYYYMMDD HH24:MI:SS') from dual;
|
||||
set heading on feedback on
|
||||
|
||||
prompt
|
||||
|
||||
prompt delete from &spuser..SAWR$SNAPSHOTS where snaptime < sysdate - &spkeep;
|
||||
delete from &spuser..SAWR$SNAPSHOTS where snaptime < sysdate - &spkeep;
|
||||
commit;
|
||||
|
||||
prompt delete from &spuser..SAWR$SESSIONS where snaptime < sysdate - &spkeep;
|
||||
delete from &spuser..SAWR$SESSIONS where snaptime < sysdate - &spkeep;
|
||||
commit;
|
||||
|
||||
prompt delete from &spuser..SAWR$SESSION_EVENTS where snaptime < sysdate - &spkeep;
|
||||
delete from &spuser..SAWR$SESSION_EVENTS where snaptime < sysdate - &spkeep;
|
||||
commit;
|
||||
|
||||
prompt delete from &spuser..SAWR$SESSION_STATS where snaptime < sysdate - &spkeep;
|
||||
delete from &spuser..SAWR$SESSION_STATS where snaptime < sysdate - &spkeep;
|
||||
commit;
|
||||
|
||||
-- compact the indexes & IOTs for saving space
|
||||
alter index SAWR$SNAPSHOTS_PK coalesce;
|
||||
alter table SAWR$SESSIONS move online;
|
||||
alter table SAWR$SESSION_STATS move online;
|
||||
alter table SAWR$SESSION_EVENTS move online;
|
||||
|
||||
undefine spuser
|
||||
undefine spkeep
|
||||
18
tpt/tools/sesspack_0.05_release/sesspack_truncate.sql
Normal file
18
tpt/tools/sesspack_0.05_release/sesspack_truncate.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
define spuser=&1
|
||||
|
||||
prompt Truncating &spuser SAWR$ tables...
|
||||
|
||||
set echo on
|
||||
|
||||
truncate table &spuser..SAWR$SNAPSHOTS;
|
||||
truncate table &spuser..SAWR$SESSIONS;
|
||||
truncate table &spuser..SAWR$SESSION_EVENTS;
|
||||
truncate table &spuser..SAWR$SESSION_STATS;
|
||||
|
||||
set echo off
|
||||
|
||||
undefine spuser
|
||||
|
||||
10
tpt/tools/sesspack_0.05_release/sesspack_vmstat.sh
Normal file
10
tpt/tools/sesspack_0.05_release/sesspack_vmstat.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Note that this is currently only for Solaris
|
||||
|
||||
while true
|
||||
do
|
||||
echo `date +%Y%m%d%H%M%S`";"BEGIN_SAMPLE > /tmp/sawr_vmstat_pipe
|
||||
vmstat -s | awk '{ print $1";"$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9 }' > /tmp/sawr_vmstat_pipe
|
||||
done
|
||||
|
||||
168
tpt/tools/sesspack_0.05_release/sr.sql
Normal file
168
tpt/tools/sesspack_0.05_release/sr.sql
Normal file
@@ -0,0 +1,168 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
set feedback off lines 200 trimspool on
|
||||
|
||||
define _tptmode = normal
|
||||
define grouping = &1
|
||||
define start_snap = &2
|
||||
define end_snap = &3
|
||||
|
||||
col wait_ms for 9999999999
|
||||
col avg_wait_ms for 99999999.9
|
||||
col ms_per_sec for 999999.9 noprint
|
||||
col pct_in_wait head "% of|Time" for 99999.9
|
||||
col module for a30 truncate
|
||||
col action for a30 truncate
|
||||
col program for a30 truncate
|
||||
col username for a15 truncate
|
||||
col osuser for a20 truncate
|
||||
col name for a30 truncate
|
||||
col machine for a20 truncate
|
||||
col histgm for a10 truncate
|
||||
|
||||
col grouping_break noprint new_value grouping_break
|
||||
col mandatory_name_col noprint new_value name_col
|
||||
--set termout off
|
||||
select replace('&grouping', ',', ' on ') as grouping_break
|
||||
, case
|
||||
when replace(lower('&grouping'), ',', ' ') like '% name %'
|
||||
or replace(lower('&grouping'), ',', ' ') like '% name'
|
||||
or replace(lower('&grouping'), ',', ' ') like 'name %'
|
||||
or trim(lower('&grouping')) = 'name'
|
||||
then '--,name'
|
||||
else ',name'
|
||||
end as mandatory_name_col
|
||||
from dual;
|
||||
--set termout on
|
||||
|
||||
break on &grouping_break skip 1
|
||||
|
||||
|
||||
select
|
||||
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
|
||||
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
|
||||
(b.snaptime - a.snaptime)*86400 dur_sec,
|
||||
(b.snaptime - a.snaptime)*86400/60 dur_min
|
||||
from
|
||||
(select snaptime from sawr$snapshots where snapid = &2) a,
|
||||
(select snaptime from sawr$snapshots where snapid = &3) b
|
||||
/
|
||||
|
||||
|
||||
rem Events delta report
|
||||
rem ==================================================================================
|
||||
|
||||
with deltas as (
|
||||
select e2.sid
|
||||
, nvl(e1.snapid, &start_snap) as begin_snapid
|
||||
, e2.snapid as end_snapid
|
||||
, nvl(e1.snaptime, e2.logon_time) as begin_snaptime
|
||||
, e2.snaptime as end_snaptime
|
||||
, greatest((e2.snaptime - nvl(e1.snaptime, e2.logon_time))*86400,1) as snap_interval
|
||||
, e2.audsid
|
||||
, e2.username
|
||||
, e2.program
|
||||
, e2.terminal
|
||||
, e2.machine
|
||||
, e2.osuser
|
||||
, e2.module
|
||||
, e2.action
|
||||
, substr(e2.name,1,45) as name
|
||||
, e2.time_waited_micro - nvl(e1.time_waited_micro,0) as wait_us
|
||||
, e2.total_waits - nvl(e1.total_waits,0) as waits
|
||||
from sawr$sess_event e1
|
||||
right outer join
|
||||
sawr$sess_event e2
|
||||
on (e1.audsid = e2.audsid
|
||||
and e1.sid = e2.sid
|
||||
and e1.serial# = e2.serial#
|
||||
and e1.logon_time = e2.logon_time
|
||||
and e1.event# = e2.event#
|
||||
and e1.snapid = &start_snap)
|
||||
where e2.snapid = &end_snap
|
||||
)
|
||||
, micros as (
|
||||
select d.*
|
||||
, round(d.wait_us/d.snap_interval) as us_per_sec
|
||||
from deltas d
|
||||
where d.waits != 0
|
||||
or d.wait_us != 0
|
||||
)
|
||||
select &grouping
|
||||
&name_col
|
||||
, rpad('#',trunc(ratio_to_report(sum(wait_us)) over (partition by &grouping)*10),'#') as histgm
|
||||
, sum(us_per_sec)/1000 as ms_per_sec
|
||||
, round(sum(us_per_sec)/10000,2) as pct_in_wait
|
||||
, (sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) as avg_wait_ms
|
||||
, sum(wait_us)/1000 as wait_ms
|
||||
, sum(waits) as waits
|
||||
from micros
|
||||
group by
|
||||
&grouping
|
||||
&name_col
|
||||
order by
|
||||
&grouping, ms_per_sec desc;
|
||||
|
||||
|
||||
rem Stats delta report
|
||||
rem ==================================================================================
|
||||
|
||||
col delta head Delta for 999999999999999
|
||||
col delta_per_sec head D/sec for 999999999999.9
|
||||
|
||||
with deltas as (
|
||||
select s2.sid
|
||||
, nvl(s1.snapid, &start_snap) as begin_snapid
|
||||
, s2.snapid as end_snapid
|
||||
, nvl(s1.snaptime, s2.logon_time) as begin_snaptime
|
||||
, s2.snaptime as end_snaptime
|
||||
, greatest((s2.snaptime - nvl(s1.snaptime, s2.logon_time))*86400,1) as snap_interval
|
||||
, s2.audsid
|
||||
, s2.username
|
||||
, s2.program
|
||||
, s2.terminal
|
||||
, s2.machine
|
||||
, s2.osuser
|
||||
, s2.module
|
||||
, s2.action
|
||||
, substr(s2.name,1,45) as name
|
||||
, s2.value - nvl(s1.value,0) as delta
|
||||
from sawr$sess_stat s1
|
||||
right outer join
|
||||
sawr$sess_stat s2
|
||||
on (s1.audsid = s2.audsid
|
||||
and s1.sid = s2.sid
|
||||
and s1.serial# = s2.serial#
|
||||
and s1.logon_time = s2.logon_time
|
||||
and s1.statistic# = s2.statistic#
|
||||
and s1.snapid = &start_snap)
|
||||
where s2.snapid = &end_snap
|
||||
)
|
||||
select &grouping
|
||||
&name_col
|
||||
, rpad('#',trunc(ratio_to_report(sum(delta)) over (partition by &grouping)*10),'#') as histgm
|
||||
, sum(delta)/avg(snap_interval) as delta_per_sec
|
||||
, sum(delta) as delta
|
||||
from deltas
|
||||
where delta != 0
|
||||
group by
|
||||
&grouping
|
||||
&name_col
|
||||
order by
|
||||
&grouping, abs(delta) desc;
|
||||
|
||||
|
||||
|
||||
break on _nonexistent
|
||||
set feedback on null ""
|
||||
190
tpt/tools/sesspack_0.05_release/srs.sql
Normal file
190
tpt/tools/sesspack_0.05_release/srs.sql
Normal file
@@ -0,0 +1,190 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
set feedback 5 lines 200 trimspool on
|
||||
|
||||
define _tptmode = normal
|
||||
define grouping = &1
|
||||
define start_snap = &2
|
||||
define end_snap = &3
|
||||
define stat_cols = "&4"
|
||||
|
||||
col wait_ms for 9999999999
|
||||
col avg_wait_ms for 99999999.9
|
||||
col ms_per_sec for 999999.9
|
||||
col module for a30 truncate
|
||||
col action for a30 truncate
|
||||
col program for a30 truncate
|
||||
col username for a15 truncate
|
||||
col osuser for a20 truncate
|
||||
col name for a30 truncate
|
||||
col machine for a20 truncate
|
||||
col histgm for a10 truncate
|
||||
|
||||
col delta head Delta for 9999999999
|
||||
col delta_per_sec head D/sec for 9999999.9
|
||||
|
||||
col grouping_break noprint new_value grouping_break
|
||||
col mandatory_name_col noprint new_value name_col
|
||||
col stat_list_cols noprint new_value stat_list
|
||||
col e2_grouping_cols noprint new_value e2_grouping
|
||||
col sa_grouping_cols noprint new_value sa_grouping
|
||||
|
||||
--set termout off
|
||||
select case
|
||||
when replace(lower('&grouping'), ',', ' ') like '% name %'
|
||||
or replace(lower('&grouping'), ',', ' ') like '% name'
|
||||
or replace(lower('&grouping'), ',', ' ') like 'name %'
|
||||
or trim(lower('&grouping')) = 'name'
|
||||
then '--,name'
|
||||
else ',name'
|
||||
end as mandatory_name_col
|
||||
, replace('&grouping', ',', ' on ') as grouping_break
|
||||
, replace(replace('e2.&grouping',' '),',',',e2.') as e2_grouping_cols
|
||||
, replace(replace('sa.&grouping',' '),',',',sa.') as sa_grouping_cols
|
||||
, replace(
|
||||
replace(
|
||||
replace('&stat_cols',', ',','),' ,',','),',',''',''') as stat_list_cols
|
||||
from dual;
|
||||
--set termout on
|
||||
|
||||
break on &grouping_break on delta_type skip 1
|
||||
|
||||
select
|
||||
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
|
||||
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
|
||||
(b.snaptime - a.snaptime)*86400 dur_sec,
|
||||
(b.snaptime - a.snaptime)*86400/60 dur_min
|
||||
from
|
||||
(select snaptime from sawr$snapshots where snapid = &start_snap) a,
|
||||
(select snaptime from sawr$snapshots where snapid = &end_snap) b
|
||||
/
|
||||
|
||||
|
||||
rem Specific stats and events delta report
|
||||
rem ==================================================================================
|
||||
with stat_deltas as (
|
||||
select s2.sid
|
||||
, nvl(s1.snapid, &start_snap) as begin_snapid
|
||||
, s2.snapid as end_snapid
|
||||
, nvl(s1.snaptime, s2.logon_time) as begin_snaptime
|
||||
, s2.snaptime as end_snaptime
|
||||
, greatest((s2.snaptime - nvl(s1.snaptime, s2.logon_time))*86400,1) as snap_interval
|
||||
, s2.audsid
|
||||
, s2.username
|
||||
, s2.program
|
||||
, s2.terminal
|
||||
, s2.machine
|
||||
, s2.osuser
|
||||
, s2.module
|
||||
, s2.action
|
||||
, substr(s2.name,1,45) as name
|
||||
, s2.value - nvl(s1.value,0) as delta
|
||||
from sawr$sess_stat s1
|
||||
right outer join
|
||||
sawr$sess_stat s2
|
||||
on (s1.audsid = s2.audsid
|
||||
and s1.sid = s2.sid
|
||||
and s1.serial# = s2.serial#
|
||||
and s1.logon_time = s2.logon_time
|
||||
and s1.statistic# = s2.statistic#
|
||||
and s1.snapid = &start_snap)
|
||||
where s2.snapid = &end_snap
|
||||
and (s2.name in ( '&stat_list' )
|
||||
or replace('&stat_list',' ') is null)
|
||||
)
|
||||
, stat_aggregates as (
|
||||
select &grouping
|
||||
&name_col
|
||||
, sum(delta)/avg(snap_interval) as delta_per_sec
|
||||
, sum(delta) as delta
|
||||
from stat_deltas
|
||||
where delta != 0
|
||||
group by
|
||||
&grouping
|
||||
&name_col
|
||||
order by
|
||||
&grouping, abs(delta) desc
|
||||
)
|
||||
, event_deltas as (
|
||||
select e2.sid
|
||||
, nvl(e1.snapid, &start_snap) as begin_snapid
|
||||
, e2.snapid as end_snapid
|
||||
, nvl(e1.snaptime, e2.logon_time) as begin_snaptime
|
||||
, e2.snaptime as end_snaptime
|
||||
, greatest((e2.snaptime - nvl(e1.snaptime, e2.logon_time))*86400,1) as snap_interval
|
||||
, e2.audsid
|
||||
, e2.username
|
||||
, e2.program
|
||||
, e2.terminal
|
||||
, e2.machine
|
||||
, e2.osuser
|
||||
, e2.module
|
||||
, e2.action
|
||||
, substr(e2.name,1,45) as name
|
||||
, e2.time_waited_micro - nvl(e1.time_waited_micro,0) as wait_us
|
||||
, e2.total_waits - nvl(e1.total_waits,0) as waits
|
||||
from sawr$sess_event e1
|
||||
right outer join
|
||||
sawr$sess_event e2
|
||||
on (e1.audsid = e2.audsid
|
||||
and e1.sid = e2.sid
|
||||
and e1.serial# = e2.serial#
|
||||
and e1.logon_time = e2.logon_time
|
||||
and e1.event# = e2.event#
|
||||
and e1.snapid = &start_snap)
|
||||
where e2.snapid = &end_snap
|
||||
and (&e2_grouping) in (select &sa_grouping from stat_aggregates sa)
|
||||
)
|
||||
, event_micros as (
|
||||
select ed.*
|
||||
, round(ed.wait_us/ed.snap_interval) as us_per_sec
|
||||
from event_deltas ed
|
||||
where ed.waits != 0
|
||||
or ed.wait_us != 0
|
||||
)
|
||||
, event_aggregates as (
|
||||
select &grouping
|
||||
&name_col
|
||||
, rpad('#',trunc(ratio_to_report(sum(wait_us)) over (partition by &grouping)*10),'#') as histgm
|
||||
, sum(wait_us)/1000 as wait_ms
|
||||
, sum(us_per_sec)/1000 as ms_per_sec
|
||||
, round(sum(us_per_sec)/10000,2) as pct_in_wait
|
||||
, (sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) as avg_wait_ms
|
||||
, sum(waits) as waits
|
||||
from event_micros
|
||||
group by
|
||||
&grouping
|
||||
&name_col
|
||||
order by
|
||||
&grouping, ms_per_sec desc
|
||||
)
|
||||
select *
|
||||
from (
|
||||
select &grouping
|
||||
, 'STAT' as delta_type
|
||||
&name_col
|
||||
, delta_per_sec
|
||||
, delta
|
||||
from stat_aggregates
|
||||
union all
|
||||
select &grouping
|
||||
, 'EVENT' as delta_type
|
||||
&name_col
|
||||
, ms_per_sec
|
||||
, waits
|
||||
from event_aggregates
|
||||
)
|
||||
order by
|
||||
&grouping, delta_type, delta_per_sec desc;
|
||||
|
||||
46
tpt/tools/sesspack_0.05_release/unprepare_user.sql
Normal file
46
tpt/tools/sesspack_0.05_release/unprepare_user.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Notes: This software is provided AS IS and doesn't guarantee anything
|
||||
-- Proofread before you execute it!
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
prompt
|
||||
prompt Dropping roles...
|
||||
prompt
|
||||
|
||||
drop role sesspack_admin_role;
|
||||
drop role sesspack_user_role;
|
||||
|
||||
prompt
|
||||
prompt Ready to revoke SAWR privileges from user &spuser
|
||||
prompt The following commands will be run:
|
||||
prompt
|
||||
|
||||
prompt revoke select on sys.v_$session from &spuser;
|
||||
prompt revoke select on sys.v_$session_wait from &spuser;
|
||||
prompt revoke select on sys.v_$session_event from &spuser;
|
||||
prompt revoke select on sys.v_$sess_time_model from &spuser;
|
||||
prompt revoke select on sys.v_$sesstat from &spuser;
|
||||
prompt revoke select on sys.v_$event_name from &spuser;
|
||||
prompt revoke select on sys.v_$statname from &spuser;
|
||||
|
||||
prompt
|
||||
pause Press CTRL-C if you don't want to run those commands, otherwise press ENTER...
|
||||
prompt
|
||||
|
||||
revoke select on sys.v_$session from &spuser;
|
||||
revoke select on sys.v_$session_wait from &spuser;
|
||||
revoke select on sys.v_$session_event from &spuser;
|
||||
revoke select on sys.v_$sess_time_model from &spuser;
|
||||
revoke select on sys.v_$sesstat from &spuser;
|
||||
revoke select on sys.v_$event_name from &spuser;
|
||||
revoke select on sys.v_$statname from &spuser;
|
||||
|
||||
whenever sqlerror continue
|
||||
39
tpt/tools/space_tools/space_usage.sql
Normal file
39
tpt/tools/space_tools/space_usage.sql
Normal file
@@ -0,0 +1,39 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
CREATE OR REPLACE PACKAGE space_tools AS
|
||||
FUNCTION get_space_usage(owner IN VARCHAR2, object_name IN VARCHAR2, segment_type IN VARCHAR2, partition_name IN VARCHAR2 DEFAULT NULL) RETURN sys.DBMS_DEBUG_VC2COLL PIPELINED;
|
||||
END space_tools;
|
||||
/
|
||||
SHOW ERR;
|
||||
|
||||
CREATE OR REPLACE PACKAGE BODY space_tools AS
|
||||
FUNCTION get_space_usage(owner IN VARCHAR2, object_name IN VARCHAR2, segment_type IN VARCHAR2, partition_name IN VARCHAR2 DEFAULT NULL) RETURN sys.DBMS_DEBUG_VC2COLL PIPELINED
|
||||
AS
|
||||
ufbl NUMBER;
|
||||
ufby NUMBER;
|
||||
fs1bl NUMBER;
|
||||
fs1by NUMBER;
|
||||
fs2bl NUMBER;
|
||||
fs2by NUMBER;
|
||||
fs3bl NUMBER;
|
||||
fs3by NUMBER;
|
||||
fs4bl NUMBER;
|
||||
fs4by NUMBER;
|
||||
fubl NUMBER;
|
||||
fuby NUMBER;
|
||||
BEGIN
|
||||
DBMS_SPACE.SPACE_USAGE(owner,object_name,segment_type, ufbl, ufby, fs1bl,fs1by, fs2bl,fs2by, fs3bl,fs3by, fs4bl,fs4by, fubl,fuby, partition_name);
|
||||
PIPE ROW('Full blocks /MB '||TO_CHAR(fubl, '999999999')||' '||TO_CHAR(fuby /1048576,'999999999'));
|
||||
PIPE ROW('Unformatted blocks/MB '||TO_CHAR(ufbl, '999999999')||' '||TO_CHAR(ufby /1048576,'999999999'));
|
||||
PIPE ROW('Free Space 0-25% '||TO_CHAR(fs1bl, '999999999')||' '||TO_CHAR(fs1by /1048576,'999999999'));
|
||||
PIPE ROW('Free Space 25-50% '||TO_CHAR(fs2bl, '999999999')||' '||TO_CHAR(fs2by /1048576,'999999999'));
|
||||
PIPE ROW('Free Space 50-75% '||TO_CHAR(fs3bl, '999999999')||' '||TO_CHAR(fs3by /1048576,'999999999'));
|
||||
PIPE ROW('Free Space 75-100% '||TO_CHAR(fs4bl, '999999999')||' '||TO_CHAR(fs4by /1048576,'999999999'));
|
||||
END get_space_usage;
|
||||
END space_tools;
|
||||
/
|
||||
SHOW ERR;
|
||||
|
||||
|
||||
|
||||
10
tpt/tools/unix/findhomes.sh
Normal file
10
tpt/tools/unix/findhomes.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# A little helper script for finding ORACLE_HOMEs for all running instances in a Linux server
|
||||
# by Tanel Poder (http://blog.tanelpoder.com)
|
||||
|
||||
printf "%6s %-20s %-80s\n" "PID" "NAME" "ORACLE_HOME"
|
||||
pgrep -lf _pmon_ |
|
||||
while read pid pname y ; do
|
||||
printf "%6s %-20s %-80s\n" $pid $pname `ls -l /proc/$pid/exe | awk -F'>' '{ print $2 }' | sed 's/bin\/oracle$//' | sort | uniq`
|
||||
done
|
||||
|
||||
58
tpt/tools/unix/heapdump_analyzer
Normal file
58
tpt/tools/unix/heapdump_analyzer
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/bin/ksh
|
||||
################################################################################
|
||||
## Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
## Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
##
|
||||
## File name: heapdump_analyzer
|
||||
## Purpose: Script for aggregating Oracle heapdump chunk sizes
|
||||
##
|
||||
## Author: Tanel Poder
|
||||
## Copyright: (c) http://www.tanelpoder.com
|
||||
##
|
||||
## Usage: 1) Take a heapdump ( read http://www.juliandyke.com )
|
||||
##
|
||||
## 2) run ./heapdump_analyzer <heapdump tracefile name>
|
||||
## For example: ./heapdump_analyzer ORCL_ora_4345.trc
|
||||
##
|
||||
## Other: Only take heapdumps when you know what you're doing!
|
||||
## Taking a heapdump on shared pool (when bit 2 in heapdump event
|
||||
## level is enabled) can hang your database for a while as it
|
||||
## holds shared pool latches for a long time if your shared pool
|
||||
## is big and heavily active.
|
||||
##
|
||||
## Private memory heapdumps are safer as only the dumped process is
|
||||
## affected.
|
||||
##
|
||||
## On Solaris you may need to replace awk with nawk in this script
|
||||
##
|
||||
################################################################################
|
||||
|
||||
if [ "$1" == "-t" ]; then
|
||||
EXCLUDE='dummy_nonexistent_12345'
|
||||
shift
|
||||
else
|
||||
EXCLUDE='Total heap size$'
|
||||
fi
|
||||
|
||||
echo
|
||||
echo " -- Heapdump Analyzer v1.03 by Tanel Poder ( https://blog.tanelpoder.com )"
|
||||
echo
|
||||
echo " Total_size #Chunks Chunk_size, From_heap, Chunk_type, Alloc_reason"
|
||||
echo " ------------ ------- ------------ ----------------- ----------------- -----------------"
|
||||
|
||||
cat $1 | awk '
|
||||
/^HEAP DUMP heap name=/ { split($0,ht,"\""); HTYPE=ht[2]; doPrintOut = 1; }
|
||||
/Chunk/{ if ( doPrintOut == 1 ) {
|
||||
split($0,sf,"\"");
|
||||
printf "%12.0f , %16s, %16s, %16s\n", $4, HTYPE, $5, sf[2];
|
||||
}
|
||||
}
|
||||
/Total heap size/ {
|
||||
printf "%12.0f , %16s, %16s, %16s\n", $5, HTYPE, "TOTAL", "Total heap size";
|
||||
doPrintOut=0;
|
||||
}
|
||||
' | grep -v "$EXCLUDE" | sort -n | uniq -c | awk '{ printf " %12.0f %s\n", $1*$2, $0 }' | sort -nr
|
||||
|
||||
echo
|
||||
|
||||
|
||||
190
tpt/tools/unix/os_explain
Normal file
190
tpt/tools/unix/os_explain
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
## Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
## Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
##
|
||||
## File name: os_explain (version 1.1)
|
||||
## Purpose: Script to explain the currently active branch of SQL plan
|
||||
## execution from Oracle server process stack trace
|
||||
##
|
||||
## Author: Tanel Poder
|
||||
## Copyright: (c) http://www.tanelpoder.com
|
||||
##
|
||||
## Usage: 1) Take a stack trace of an Oracle process (either by using a
|
||||
## a debugger, pstack or extract the stack from a corefile,
|
||||
## save it to a file (pstack.txt for example)
|
||||
## 2) run ./os_explain <stack_trace_file>
|
||||
## For example: ./os_explain pstack.txt
|
||||
##
|
||||
##
|
||||
##
|
||||
## Alternatively you can pipe pstack output directly to os_explain
|
||||
## STDIN:
|
||||
##
|
||||
## pstack <SPID> | ./os_explain
|
||||
##
|
||||
## Other: Get stack using pstack on Solaris and Linux, using procstack
|
||||
## on AIX and by using pstack on recent versions of HP-UX.
|
||||
## Older HP-UX versions may require a debugger for getting stack
|
||||
## from OS. As an alternative (especially on Windows) you could
|
||||
## use ORADEBUG DUMP ERRORSTACK for dumping stack of a process.
|
||||
## Note that ORADEBUG's stack dump mechanism is not 100% safe
|
||||
## on active processes
|
||||
##
|
||||
## Most of Oracle kernel function prefix translations are based
|
||||
## on Metalink note 175982.1 (google for it, it's gone from the
|
||||
## Oracle site)
|
||||
##
|
||||
## On Solaris you may need to replace awk with nawk in this script
|
||||
## I don't remember why anymore, but for some reason I used it
|
||||
##
|
||||
################################################################################
|
||||
|
||||
# LIFO line reverser
|
||||
f_lifo() {
|
||||
|
||||
#echo Entering f_lifo()
|
||||
|
||||
MAX_ARRAY=1023 # Max stack array depth. You can use 4095 here but older linuxes and hp-ux shell may not like it
|
||||
|
||||
i=$MAX_ARRAY
|
||||
|
||||
IFS=^
|
||||
while read input ; do
|
||||
array[i]=$input
|
||||
((i=i-1))
|
||||
done
|
||||
|
||||
i=1
|
||||
|
||||
for output in ${array[@]} ; do
|
||||
|
||||
if test "$1" = "-n" ; then
|
||||
printf "%4d %s\n" $i $output
|
||||
else
|
||||
printf "%s\n" $output
|
||||
fi
|
||||
((i=i+1))
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
|
||||
TRANSLATION_STRING='
|
||||
/----------------- lwp# 2/,$d;
|
||||
s/(.*//;
|
||||
s/ [[0-9][a-f]]{16} /./;
|
||||
s/qerae/AND-EQUAL: /g;
|
||||
s/qerba/BITMAP INDEXAND : /g;
|
||||
s/qerbc/BITMAP INDEX COMPACTION: /g;
|
||||
s/qerbi/BITMAP INDEX CREATION: /g;
|
||||
s/qerbm/MINUS: /g;
|
||||
s/qerbo/BITMAP INDEX OR: /g;
|
||||
s/qerbt/BITMAP CONVERT: /g;
|
||||
s/qerbu/BITMAP INDEX UNLIMITED-OR: /g;
|
||||
s/qerbx/BITMAP INDEX ACCESS: /g;
|
||||
s/qercb/CONNECT BY: /g;
|
||||
s/qercbi/SUPPORT FOR CONNECT BY: /g;
|
||||
s/qerco/COUNT: /g;
|
||||
s/qerdl/DELETE: /g;
|
||||
s/qerep/EXPLOSION: /g;
|
||||
s/qerff/FIFO BUFFER: /g;
|
||||
s/qerfi/FIRST ROW: /g;
|
||||
s/qerfl/FILTER DEFINITION: /g;
|
||||
s/qerfu/UPDATE: /g;
|
||||
s/qerfx/FIXED TABLE: /g;
|
||||
s/qergi/GRANULE ITERATOR: /g;
|
||||
s/qergr/GROUP BY ROLLUP: /g;
|
||||
s/qergs/GROUP BY SORT: /g;
|
||||
s/qerhc/HASH CLUSTERS: /g;
|
||||
s/qerhj/HASH JOIN: /g;
|
||||
s/qeril/IN-LIST: /g;
|
||||
s/qerim/INDEX MAINTENANCE: /g;
|
||||
s/qerix/INDEX: /g;
|
||||
s/qerjot/NESTED LOOP JOIN: /g;
|
||||
s/qerjo/NESTED LOOP OUTER: /g;
|
||||
s/qerle/LINEAR EXECUTION IMPLEMENTATION: /g;
|
||||
s/qerli/PARALLEL CREATE INDEX: /g;
|
||||
s/qerlt/LOAD TABLE: /g;
|
||||
s/qerns/GROUP BY NO SORT: /g;
|
||||
s/qeroc/OBJECT COLLECTION ITERATOR: /g;
|
||||
s/qeroi/EXTENSIBLE INDEXING QUERY COMPONENT: /g;
|
||||
s/qerpa/PARTITION: /g;
|
||||
s/qerpf/QUERY EXECUTION PREFETCH: /g;
|
||||
s/qerpx/PARALLELIZER: /g;
|
||||
s/qerrm/REMOTE: /g;
|
||||
s/qerse/SET IMPLEMENTATION: /g;
|
||||
s/qerso/SORT: /g;
|
||||
s/qersq/SEQUENCE NUMBER: /g;
|
||||
s/qerst/QUERY EXECUTION STATISTICS: /g;
|
||||
s/qertb/TABLE ACCESS: /g;
|
||||
s/qertq/TABLE QUEUE: /g;
|
||||
s/qerua/UNION-ALL: /g;
|
||||
s/qerup/UPDATE: /g;
|
||||
s/qerus/UPSERT: /g;
|
||||
s/qervw/VIEW: /g;
|
||||
s/qerwn/WINDOW: /g;
|
||||
s/qerxt/EXTERNAL TABLE FETCH : /g;
|
||||
s/opifch2/SELECT FETCH: /g
|
||||
s/qergh/HASH GROUP BY: /g
|
||||
'
|
||||
|
||||
# main()
|
||||
|
||||
case `uname -s` in
|
||||
Linux)
|
||||
FUNCPOS=4
|
||||
;;
|
||||
SunOS)
|
||||
FUNCPOS=2
|
||||
;;
|
||||
*)
|
||||
FUNCPOS=2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$1X" == "-aX" ] ; then
|
||||
FILTER="^\$|oracle|----------"
|
||||
INDENT=" "
|
||||
shift
|
||||
else
|
||||
FILTER="^\$|\?\?|oracle|----------"
|
||||
TRANSLATION_STRING="/opifch /,\$d;/opiefn0/,\$d;/opiodr/,\$d;/opiexe/,\$d; $TRANSLATION_STRING"
|
||||
INDENT=" "
|
||||
fi
|
||||
|
||||
if [ "$1X" == "-kX" ] ; then
|
||||
FUNCPOS=2 # this is for linux kernel stack samples from /proc/PID/stack
|
||||
TRANSLATION_STRING="s/+.*//g; $TRANSLATION_STRING"
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
|
||||
sed -e "$TRANSLATION_STRING" \
|
||||
| egrep -v "$FILTER" \
|
||||
| sed 's/^ *//g;s/__PGOSF[0-9]*_//' \
|
||||
| awk -F" " "{ for (f=$FUNCPOS; f <= NF; f++) { printf \"%s \", \$f }; printf \"\n\" }" \
|
||||
| f_lifo \
|
||||
| awk "
|
||||
BEGIN{ option=\" \" } /rwsfcd/{ option=\"* \" } !/rwsfcd/{ pref=(pref \"$INDENT\") ;
|
||||
print pref option \$0 ; option=\" \" }
|
||||
"
|
||||
else
|
||||
|
||||
for i in $* ; do
|
||||
sed -e "$TRANSLATION_STRING" < $i \
|
||||
| egrep -v "$FILTER" \
|
||||
| sed 's/^ *//g;s/__PGOSF[0-9]*_//' \
|
||||
| awk -F" " "{ for (f=$FUNCPOS; f <= NF; f++) { printf \"%s \", \$f }; printf \"\n\" }" \
|
||||
| f_lifo \
|
||||
| awk "
|
||||
BEGIN{ option=\" \" } /rwsfcd/{ option=\"* \" } !/rwsfcd/{ pref=(pref \"$INDENT\") ;
|
||||
print pref option \$0 ; option=\" \" }
|
||||
"
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
# that's all!
|
||||
|
||||
24
tpt/tools/unix/procio.sh
Normal file
24
tpt/tools/unix/procio.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tiny Linux /proc/<pid>/io demo script by Tanel Poder
|
||||
# http://www.tanelpoder.com
|
||||
|
||||
PID=$1
|
||||
TMPFILE1=/tmp/procio.${PID}.tmp1
|
||||
TMPFILE2=/tmp/procio.${PID}.tmp2
|
||||
SLEEP=5
|
||||
|
||||
trap 'rm -f $TMPFILE1 $TMPFILE2 ; exit 0' 0
|
||||
|
||||
echo Sampling process $PID IO every $SLEEP seconds...
|
||||
|
||||
cat /proc/$PID/io > $TMPFILE2
|
||||
|
||||
while true ; do
|
||||
mv $TMPFILE2 $TMPFILE1
|
||||
sleep $SLEEP
|
||||
cat /proc/$PID/io > $TMPFILE2
|
||||
paste $TMPFILE1 $TMPFILE2 | awk '{ printf "%30s %d\n", $1, $4-$2 }'
|
||||
echo
|
||||
done
|
||||
|
||||
170
tpt/tools/unix/procmm.py
Normal file
170
tpt/tools/unix/procmm.py
Normal file
@@ -0,0 +1,170 @@
|
||||
#!/bin/env python
|
||||
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
# perms
|
||||
# r = read
|
||||
# w = write
|
||||
# x = execute
|
||||
# s = shared
|
||||
# p = private (copy on write)
|
||||
|
||||
import sys, os, pwd, re, json
|
||||
|
||||
re_mapheader = re.compile('[0-9a-f]+-[0-9a-f]+', re.IGNORECASE)
|
||||
|
||||
def readFileLines(name):
|
||||
with file(name) as f:
|
||||
s = f.readlines()
|
||||
return s
|
||||
|
||||
def readFile(name):
|
||||
x=readFileLines(name)
|
||||
if x:
|
||||
return x[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def getProcRec(pid):
|
||||
try:
|
||||
mr={}
|
||||
mr['pid'] = pid
|
||||
mr['comm'] = readFile('/proc/' + pid + '/comm')
|
||||
mr['cmdline'] = readFile('/proc/' + pid + '/cmdline')
|
||||
mr['username'] = pwd.getpwuid(os.stat('/proc/' + pid).st_uid).pw_name
|
||||
|
||||
except IOError as e:
|
||||
print "Process gone"
|
||||
except Exception as e:
|
||||
print "error", e
|
||||
raise
|
||||
return mr
|
||||
|
||||
def getProcMemData(pid):
|
||||
memseg={}
|
||||
memdetail={}
|
||||
allmemseg={}
|
||||
allmemdetail={}
|
||||
|
||||
try:
|
||||
for l in readFileLines('/proc/' + pid + '/smaps'):
|
||||
if re_mapheader.match(l):
|
||||
memseg['baddr_hex'] = l.split()[0].split('-')[0]
|
||||
memseg['eaddr_hex'] = l.split()[0].split('-')[1]
|
||||
memseg['perms'] = l.split()[1]
|
||||
memseg['offset'] = l.split()[2]
|
||||
memseg['dev'] = l.split()[3]
|
||||
memseg['inode'] = l.split()[4]
|
||||
if len(l.split()) >= 6:
|
||||
s = l.split()[5]
|
||||
if s.startswith('/dev/shm'):
|
||||
s = '/dev/shm'
|
||||
#re.sub('', '', s)
|
||||
#print "s =", s
|
||||
memseg['name'] = s
|
||||
else:
|
||||
memseg['name'] = '[anon]'
|
||||
memseg['baddr'] = int(memseg['baddr_hex'], 16)
|
||||
memseg['eaddr'] = int(memseg['eaddr_hex'], 16)
|
||||
memseg['size'] = memseg['eaddr'] - memseg['baddr']
|
||||
|
||||
allmemseg[memseg['name']] = memseg
|
||||
else:
|
||||
# smaps format example:
|
||||
# Size: 136 kB
|
||||
# Rss: 40 kB ...
|
||||
memdetail[l.split()[0].replace(':','')] = memdetail.get(l.split()[0].replace(':',''), 0) + int(l.split()[1])
|
||||
|
||||
allmemdetail[memseg['name']] = memdetail
|
||||
|
||||
return allmemseg, allmemdetail
|
||||
|
||||
except IOError as e:
|
||||
print "Process gone"
|
||||
except Exception as e:
|
||||
print "error", e
|
||||
raise
|
||||
|
||||
def getProcMemDataSum(pidlist):
|
||||
memsum = {}
|
||||
for p in pidlist:
|
||||
procrec = getProcRec(p)
|
||||
#print "\n============ PID: %d %s" % ( int(procrec['pid']), procrec['cmdline'].replace('\x00','') )
|
||||
memseg, memdata = getProcMemData(p)
|
||||
#print memseg
|
||||
for ms in memseg:
|
||||
memsum[ms] = memdata[ms]
|
||||
#for i in memdata[ms]:
|
||||
# #print "%-25s %10d kB %s" % ( i, memdata[ms][i], ms )
|
||||
# memsum[(ms,i)] = memsum.get((ms,i), 0) + memdata[ms][i]
|
||||
|
||||
return memsum
|
||||
|
||||
def main(argv):
|
||||
memdatasum = getProcMemDataSum(argv)
|
||||
#print memdatasum
|
||||
#print json.dumps(memdatasum, indent=4)
|
||||
print "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %s" % (
|
||||
'VSize'
|
||||
, 'PTE'
|
||||
, 'Locked'
|
||||
, 'MMUPages'
|
||||
, 'Priv_Clean'
|
||||
, 'Priv_Dirty'
|
||||
, 'Pss'
|
||||
, 'Referenced'
|
||||
, 'Rss'
|
||||
, 'Shr_Clean'
|
||||
, 'Shr_Dirty'
|
||||
, 'Swap'
|
||||
, ' Segment_Name'
|
||||
)
|
||||
print "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %s" % (
|
||||
'----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, ' ----------------------------------------------------------------------'
|
||||
)
|
||||
for mseg in memdatasum:
|
||||
m = memdatasum[mseg]
|
||||
print "%10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %s" % (
|
||||
m.get('Size', 0)
|
||||
, m.get('KernelPageSize', 0)
|
||||
, m.get('Locked', 0)
|
||||
, m.get('MMUPageSize', 0)
|
||||
, m.get('Private_Clean', 0)
|
||||
, m.get('Private_Dirty', 0)
|
||||
, m.get('Pss', 0)
|
||||
, m.get('Referenced', 0)
|
||||
, m.get('Rss', 0)
|
||||
, m.get('Shared_Clean', 0)
|
||||
, m.get('Shared_Dirty', 0)
|
||||
, m.get('Swap', 0)
|
||||
, mseg
|
||||
)
|
||||
|
||||
#for a in argv:
|
||||
# procrec = getProcRec(a)
|
||||
# print "\n============ PID: %d %s" % ( int(procrec['pid']), procrec['cmdline'].replace('\x00','') )
|
||||
# memseg, memdata = getProcMemData(a)
|
||||
# #for i in sorted(memdata, key=memdata.get, reverse=False):
|
||||
# for i in sorted(memdata, reverse=False):
|
||||
# print "%-25s %10d kB" % ( i, memdata[i] )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
|
||||
134
tpt/tools/unix/procmm.sh
Normal file
134
tpt/tools/unix/procmm.sh
Normal file
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/sh
|
||||
|
||||
################################################################################
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
#
|
||||
# Script: procmm.sh (Process Memory Matrix) v1.03
|
||||
#
|
||||
# Purpose: Show process memory usage for different mappings and segment types
|
||||
#
|
||||
# Copyright: Copyright (c) 2010 Tanel Poder ( http://tech.e2sn.com )
|
||||
# All rights reserved.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# Usage: procmm.sh [-t|-a] <pidlist>
|
||||
#
|
||||
# Without any special options procmm.sh will show you a matrix
|
||||
# of the processes address space segment types and their respective
|
||||
# memory usages/reservations, separately for every process in the
|
||||
# pidlist.
|
||||
#
|
||||
# -t option will only show total memory usage of all processes
|
||||
# listed in pidlist. Any ANON memory usage and swap reservation
|
||||
# for *shared* mappings (mapped binaries, libraries, shared memory
|
||||
# segments - Oracle SGA) is not shown.
|
||||
# Note that pmap command is not cheap one, so you probably do not
|
||||
# want to run it over many processes frequently
|
||||
#
|
||||
# -a option will list ANON memory usage and swap reservation also for
|
||||
# shared mappings. The -t and -a options are mutually exclusive
|
||||
# as it doesn not make sense to sum together the same shared mapping
|
||||
# memory usage of multiple processes.
|
||||
#
|
||||
# Comments: This script currently only works on Solaris as the pmap command
|
||||
# on other platforms doesnt currently show all required info. On
|
||||
# Linux it will be possible to read this info from proc filesystem (TODO)
|
||||
#
|
||||
# If you are getting "address space is changing" errors from pmap then try
|
||||
# again or suspend the process for duration of this script run.
|
||||
# NB! Suspending processes may be dangerous in some cases (such as when
|
||||
# it is holding a hot latch) so you better know what you are doing.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
get_matrix() {
|
||||
p_pid="$1"
|
||||
#[ "$1" -eq 0 ] && p_pid="all" || p_pid=$1
|
||||
#pmap -x $p_pid | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" | nawk ''
|
||||
join -j 1 /tmp/procmm-x.$$ /tmp/procmm-s.$$ > /tmp/blah
|
||||
join -j 1 /tmp/procmm-x.$$ /tmp/procmm-s.$$ | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" | nawk '
|
||||
{
|
||||
item=$7
|
||||
#print "before", s
|
||||
sub(/.*\.so.*/, "lib", item)
|
||||
#print "after", s
|
||||
#item = gensub(/.*\.so.*/, "lib", "g", $7)
|
||||
#item = gensub(/lib.+|ld\..+/, "lib", "g", $7)
|
||||
#print $7 " = " item
|
||||
vmem[item] += $2
|
||||
rss[item] += $3
|
||||
anon[item] += $4
|
||||
locked[item] += $5
|
||||
swap[item] += $9
|
||||
#print $0
|
||||
}
|
||||
END {
|
||||
printf "%6-s %20s %12s %12s %12s %12s %12s\n", "PID", "SEGMENT_TYPE", "VIRTUAL", "RSS", "ANON", "LOCKED", "SWAP_RSVD"
|
||||
printf "------ -------------------- ------------ ------------ ------------ ------------ ------------\n"
|
||||
for (x in vmem) {
|
||||
printf "%6-d %20s %12d %12d %12d %12d %12d\n", '$p_pid', x, vmem[x], rss[x], anon[x], locked[x], swap[x]
|
||||
|
||||
total_vmem += vmem[x]
|
||||
total_rss += rss[x]
|
||||
total_anon += anon[x]
|
||||
total_locked += locked[x]
|
||||
total_swap += swap[x]
|
||||
}
|
||||
|
||||
printf "------ -------------------- ------------ ------------ ------------ ------------ ------------\n"
|
||||
printf "%6-d %20s %12d %12d %12d %12d %12d\n\n", '$p_pid', "TOTAL(kB)", total_vmem, total_rss, total_anon, total_locked, total_swap
|
||||
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
echo "\n-- procmm.sh: Process Memory Matrix v1.03 by Tanel Poder ( http://tech.e2sn.com )"
|
||||
|
||||
if [ $# -lt 1 ] ; then
|
||||
echo "\nUsage:\n"
|
||||
echo " $0 [-a|-t] <pidlist>\n"
|
||||
echo " Option -a would report swap reservations and anonymous memory"
|
||||
echo " for shared mappings (like Oracle SGA) too\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# defaults
|
||||
pmap_option=""
|
||||
compute_total=0
|
||||
|
||||
case "$1" in
|
||||
"-a") pmap_option="a" ; shift ;;
|
||||
"-t") compute_total=1 ; shift ;;
|
||||
esac
|
||||
|
||||
echo "-- All numbers are shown in kilobytes\n"
|
||||
|
||||
pidlist="$*"
|
||||
#echo $pidlist
|
||||
|
||||
if [ $compute_total -eq 0 ]; then
|
||||
for pid in $pidlist; do
|
||||
# ps -opid,vsz,rss,args -p $pid | nawk '/ *[0-9]+/{ printf "-- ps info: PID=%d VSZ=%d RSS=%d ARGS=%s\n\n", $1,$2,$3,$4 }'
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
pmap -x$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]+:" > /tmp/procmm-x.$$
|
||||
pmap -S$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]+:" > /tmp/procmm-s.$$
|
||||
get_matrix $pid
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
done
|
||||
else
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
printf "Total PIDs %d, working: " $#
|
||||
for pid in $pidlist; do
|
||||
# ps -opid,vsz,rss,args -p $pid | nawk '/ *[0-9]+/{ printf "-- ps info: PID=%d VSZ=%d RSS=%d ARGS=%s\n\n", $1,$2,$3,$4 }'
|
||||
pmap -x$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" >> /tmp/procmm-x.$$
|
||||
pmap -S$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" >> /tmp/procmm-s.$$
|
||||
printf "."
|
||||
done
|
||||
printf "\n\n"
|
||||
get_matrix 0
|
||||
echo "-- Note that in Total (-t) calculation mode it makes sense to look into ANON and SWAP_RSVD"
|
||||
echo "-- totals only as other numbers may be heavily \"doublecounted\" due to overlaps of shared mappings\n"
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
fi
|
||||
32
tpt/tools/unix/runqlat.sh
Normal file
32
tpt/tools/unix/runqlat.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tiny Linux /proc/<pid>/schedstat demo script by Tanel Poder
|
||||
# https://tanelpoder.com
|
||||
#
|
||||
# You may want to run this with high priority:
|
||||
# sudo nice -n -10 ./runqlat.sh PID
|
||||
#
|
||||
# currently this script assumes that it will speep exactly for $SLEEP
|
||||
# seconds, but it can itself be affected by CPU overload and you may
|
||||
# see values that don't add up to 1000 ms per sec
|
||||
# (or negative percentages in the derived BLKD% column)
|
||||
|
||||
PID=$1
|
||||
SLEEP=1
|
||||
|
||||
echo Sampling /proc/$PID/schedstat every $SLEEP seconds...
|
||||
|
||||
printf "%6s %6s %6s\n" "CPU%" "RUNQ%" "SLP%"
|
||||
while true ; do
|
||||
read -r CPU_NS_1 LAT_NS_1 SLICES_ON_THIS_CPU_1 < /proc/$PID/schedstat
|
||||
sleep $SLEEP
|
||||
read -r CPU_NS_2 LAT_NS_2 SLICES_ON_THIS_CPU_2 < /proc/$PID/schedstat
|
||||
|
||||
ON_CPU=$((($CPU_NS_2-$CPU_NS_1)/10000000))
|
||||
ON_RUNQ=$((($LAT_NS_2-$LAT_NS_1)/10000000))
|
||||
OTHER=$((100-($ON_CPU+ON_RUNQ)))
|
||||
|
||||
printf "%6d %6d %6d" $ON_CPU $ON_RUNQ $OTHER
|
||||
echo
|
||||
done
|
||||
|
||||
49
tpt/tools/unix/ssexplorer.sh
Normal file
49
tpt/tools/unix/ssexplorer.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# System State Dump "explorer"
|
||||
# It just adds links to parent State Object location in the file for easier navigation
|
||||
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
TRACEFILE=$1
|
||||
OUTPUTFILE=$1.html
|
||||
|
||||
sed -e '
|
||||
s/</\</g
|
||||
s/>/\>/g
|
||||
s/SO: \(0x[A-Fa-f0-9]*\)/<a name="\1"><mark>SO: \1<\/mark><\/a>/
|
||||
s/LIBRARY HANDLE:\(0x[A-Fa-f0-9]*\)/<a name="\1">LIBRARY HANDLE:\1<\/a>/
|
||||
s/owner: \(0x[A-Fa-f0-9]*\)/owner: <a href="#\1">\1<\/a>/
|
||||
s/handle=\(0x[A-Fa-f0-9]*\)/handle=<a href="#\1">\1<\/a>/
|
||||
' $TRACEFILE | awk '
|
||||
BEGIN { print "<html><head><title>System State Dump Explorer by Tanel Poder</title></head><body><pre><code>" }
|
||||
{ print $0 }
|
||||
END { print "</code></pre></body></html>" }
|
||||
' > $OUTPUTFILE
|
||||
|
||||
echo Done writing into $OUTPUTFILE
|
||||
echo
|
||||
ls -l $OUTPUTFILE
|
||||
|
||||
|
||||
#awk '
|
||||
#
|
||||
# BEGIN { print "<html><head><title>System State Dump Explorer by Tanel Poder</title></head><body><pre><code>" }
|
||||
#
|
||||
# /0x[A-Fa-f0-9]/ { gsub( /(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0 ) }
|
||||
#
|
||||
## /SO: 0x[A-Za-z0-9]/ {
|
||||
## match($0, /(0x[A-Fa-f0-9]*),/ , arr)
|
||||
## printf ("<a name=\"%s\"></a>%s\n", arr[1], gsub( /(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0 ) )
|
||||
##
|
||||
## }
|
||||
## !/SO: 0x[A-Fa-f0-9]/ { gsub(/(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0) ; printf("%s\n", $0) }
|
||||
#
|
||||
#
|
||||
# END { print "</code></pre></body></html>" }
|
||||
#
|
||||
#
|
||||
#' | awk '/SO: / { sub( /<a href=/, "<a name=" ) }' > > $1.html
|
||||
|
||||
|
||||
24
tpt/tools/unix/strip_stack
Normal file
24
tpt/tools/unix/strip_stack
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/ksh
|
||||
#
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
# strip_stack by Tanel Poder (www.tanelpoder.com)
|
||||
#
|
||||
# strips program counter function offsets and aggregates dtrace stack sampler output
|
||||
#
|
||||
# usage: strip_stack <filename>
|
||||
#
|
||||
|
||||
cat $1 | sed 's/^ *//;s/+.*$//' | \
|
||||
awk '/^$/{ printf "\n" }/^[0-9]*$/{ printf ";%s", $1 }/[a-z]/{ printf "%s<-", $1 }END{ printf "\n" }' | \
|
||||
sort | \
|
||||
awk -F";" '
|
||||
/NR==1/{ sum=0; total=0; oldstack=$2 }
|
||||
{
|
||||
if (oldstack==$2) {sum+=$3;total+=$3}
|
||||
else {printf "%d %s\n", sum, oldstack; oldstack=$2; sum=$3}
|
||||
}
|
||||
END {printf "%d %s\n%d total samples\n", sum, oldstack,total}
|
||||
' | \
|
||||
sort -bnr
|
||||
|
||||
Reference in New Issue
Block a user