Tengo un escenario donde queremos monitorizar información de sesiones entrando en juego paralelismo.
¿Qué me dice el sentido común? ¿Queremos monitorizar en un monitor de sesiones activas procesos slave o los coordinadores? En nuestro escenario no tiene sentido duplicar sesiones en el monitor atendiendo a slaves. Queremos el proceso principal, el que coordina o si no es paralelo la sesión activa.
Para ello me he valido de la siguiente consulta:
SELECT
a.inst_id,
a.sid,
a.username,
a.machine,
a.program,
a.state,
a.module,
a.sql_exec_start,
a.blocking_session,
a.serial#,
b.spid,
a.action,
a.resource_consumer_group
FROM
gv$session a,
gv$process b
WHERE
( a.paddr = b.addr )
AND ( a.status LIKE 'ACTIVE' OR a.blocking_session IS NOT NULL )
AND a.sql_exec_start IS NOT NULL
AND a.username IS NOT NULL
and a.inst_id=b.inst_id
AND NOT EXISTS (
-- Discrimino los slaves
SELECT 1
FROM GV$PX_SESSION px
WHERE px.SID = a.SID AND px.SERIAL# = a.SERIAL# AND px.INST_ID = a.INST_ID and px.qcinst_id is not null
);
Ubicamos PID en el nodo que aplica y discriminamos slaves, queremos solo una entrada por padre.
Por qué he tenido ésta inquietud? Porque aunque las consultas entre por un DOP contenido por Resource Manager con máximo paralelismo de 1, la consultas por GV$, en mi caso en un RAC de 2 nodos, siempre van a mostrar dos sesiones activas debido al siguiente comportamiento:
When you query a GV$ view one PX server is allocated on each instance, these PX servers are not counted against parallel_max_servers so they do not effect the number of PX servers that can be used by statements accessing other objects.
Oracle controls and maintains all aspects of PZ processes. Setting parallel_max_servers to 0 will not prevent Oracle from starting PZ processes in a RAC environment if a GV$ query is issued. Setting parallel_force_local to TRUE does not restrict PZ operations to a specific instance. PZ processes are always used for gv$ queries regardless of any parallel_* parameter setting.
En resumen, el límite de DOP de 1 no aplica ni se puede contener para las GV$, en mi caso siempre abre 2 sesiones (una por nodo). Duplicando de esta manera sesiones activas en el monitor de sesiones.
Si queremos descartar las sesiones que consulten una GV$ adaptamos la consulta de la siguiente manera:
with paralelas as (
SELECT px.sid,px.inst_id, pp.serial#
FROM GV$PX_SESSION px,
GV$PX_PROCESS pp
WHERE px.SID = pp.SID
AND px.INST_ID= pp.INST_ID
and (px.qcinst_id is not null or pp.is_gv='TRUE')
)
SELECT
a.inst_id,
a.sid,
a.username,
a.machine,
a.program,
a.state,
a.module,
a.sql_exec_start,
a.blocking_session,
a.serial#,
b.spid,
a.action,
a.resource_consumer_group
FROM
gv$session a,
gv$process b
WHERE
( a.paddr = b.addr )
AND a.sql_exec_start IS NOT NULL
AND a.username IS NOT NULL
AND a.sid != (
SELECT
sys_context('USERENV', 'SID')
FROM
dual
)
and a.type = 'USER'
and a.inst_id=b.inst_id
AND NOT EXISTS (
SELECT 1
FROM paralelas par
WHERE par.sid = a.SID
AND par.INST_ID = a.INST_ID
)
ORDER BY
upper(a.machine),
upper(a.program);