Hace unos días recibí un correo de un suscriptor. La pregunta parecía simple… pero venía con truco:
Buenos días Javier, Tengo dos usuarios de base de datos: 1. OWNER 2. DBA El usuario DBA crea un Job Scheduler donde el propietario del Job es OWNER. El Job donde el propietario es OWNER y el creador es DBA corre sin problemas. Resulta que el usuario dueño de la cuenta DBA se retira de la empresa y la cuenta DBA es eliminada. Pregunta capciosa: ¿Qué pasa con el Job Scheduler creado por el usuario? 1) ¿Corre normal? 2) ¿Falla? ¿Por qué? Saludos,
La respuesta “automática” que muchos daríamos (yo incluido) es: Si el job “es de” OWNER y OWNER sigue existiendo, debería seguir corriendo.
Pero el Scheduler guarda más información de la que solemos mirar por costumbre… y ahí es donde aparecen los sustos.
Mirar solo la columna OWNER por deformación profesional
A mi me pasa el primero.
Siempre voy a ver OWNER para saber quién es el propietario de un objeto. Puede ser que una tabla sea propietario un usuario, y el índice pertenezca a SYSTEM (si lo ha creado un DBA, a veces suele pasar), o quién es el propietario de un dblink, un sinónimo,…
Así que OWNER es la columna de referencia. Pero en el Scheduler existe otro concepto que suele pasar desapercibido: el usuario creador del job.
En los casos en los que el creador y el propietario son el mismo, no hay gran problema. Incluso cuando los jobs están creados por SYS o SYSTEM, podemos tener la garantía que el usuario creador va a existir siempre, pero aquí nos preocupa un escenario muy concreto: cuando OWNER y JOB_CREATOR son distintos.
Eso ocurre, por ejemplo, cuando un DBA (o un usuario con privilegios tipo CREATE ANY JOB) crea jobs “en nombre de” otro esquema.
¿Qué dice la documentación… y qué omite?
La documentación del Scheduler te explica el modelo, los privilegios, los objetos (jobs, programs, schedules, chains), y deja claro que se pueden administrar jobs de distintas formas.
Pero normalmente lo hace desde el punto de vista “funcional”: Habla de la creación, habilitarlo/deshabilitarlo, monitorizarlo,… pero no entra en la recomendación de buenas prácticas, ni te advierte de las consecuencias colaterales del offboarding (cuando se elimina la cuenta de una persona por política de seguridad).
Y aquí, en la documentación, echo en falta una nota/advertencia que diga algo así:
- “Si haces
DROP USERdel creador, aunque el owner exista, el job queda en estado BROKEN.”
AskTom y Oracle Support
Pues, al parecer, ésto no sólo le ocurrió a este suscriptor ni es es una paranoia teórica. Le ha pasado a más de uno y lo podemos ver como caso real en AskTom (Chris Saxon), donde al eliminar (DROP USER) al creador, algunos jobs pasan a estado roto. Además, en el log aparece un el motivo definido de forma explícita:
REASON="Job creator: <usuario> dropped"
Referencia (AskTom):
https://asktom.oracle.com/ords/f?p=100:11:0::::P11_QUESTION_ID:9537363000346826584
También existe una nota de soporte que corrobora esta casuistica (en el sentido de “esto puede pasar y hay explicación”), aunque, en mi opinión, ésto deberíamos leerlo en la documentación y no en soporte, cuando vemos que los jobs quedan rotos sin que el OWNER haya sufrido ningún cambio.
Es decir, en muchos equipos el problema se descubre cuando el job falla.
Y hay que tener cuidado, porque recrear el usuario «creador» no resuelve el problema.
Laboratorio
Connected to:
Oracle AI Database 26ai Enterprise Edition Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.26.0.0.0
SQL> CREATE USER owner IDENTIFIED BY "OD98@@ownerDb76";
User created.
SQL> CREATE USER javier_dba IDENTIFIED BY "JD12!!cafeDB34";SQL>
User created.
SQL> GRANT CREATE SESSION TO owner, javier_dba;
Grant succeeded.
SQL> GRANT CREATE ANY JOB, DBA TO javier_dba;
Grant succeeded.
SQL> GRANT SELECT_CATALOG_ROLE TO owner;
Grant succeeded.
SQL> CONNECT javier_dba/"JD12!!cafeDB34"@DBORA23ai
Connected.
SQL> BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'OWNER.TESTJ',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN NULL; END;',
repeat_interval => 'FREQ=MINUTELY',
enabled => TRUE,
auto_drop => FALSE
);
END;
/
2 3 4 5 6 7 8 9 10 11
PL/SQL procedure successfully completed.
-- DESDE OTRA TERMINAL, COMO USUARIO SYS o DBA
Connected to:
Oracle AI Database 26ai Enterprise Edition Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.26.0.0.0
SQL> set lines 200
SQL> column owner format a20
SQL> column job_name format a20
SQL> column job_creator format a20
SQL> SELECT owner, job_name, job_creator, enabled, state
2 FROM dba_scheduler_jobs
3 WHERE owner = 'OWNER' AND job_name = 'TESTJ';
OWNER JOB_NAME JOB_CREATOR ENABL STATE
-------------------- -------------------- -------------------- ----- ---------------
OWNER TESTJ JAVIER_DBA TRUE SCHEDULED
-- CUIDADO! en DBA_SCHEDULER_JOB_LOG no tenemos ninguna información sobre el creador! Ni siquiera CREDENTIAL_OWNER nos informa de ello.
SQL> SELECT owner, job_name, credential_owner, destination_owner, log_date, status, additional_info
2 FROM dba_scheduler_job_log
3 WHERE owner = 'OWNER' AND job_name = 'TESTJ'
4 ORDER BY log_date DESC
5 FETCH FIRST 10 ROWS ONLY;
OWNER JOB_N CRE DE LOG_DATE STATUS ADDITIONAL_INFO
---------- ----- --- -- ----------------------------------- -------------------- --------------------
OWNER TESTJ 10-FEB-26 12.24.13.100109 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.23.12.904160 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.22.12.711332 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.21.12.504966 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.20.12.494228 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.19.12.292930 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.18.12.289176 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.17.13.093724 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.16.12.892626 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.15.12.884613 PM +00:00 SUCCEEDED
10 rows selected.
SQL> drop user javier_dba;
User dropped.
SQL> SELECT owner, job_name, credential_owner, destination_owner, log_date, status, additional_info
2 FROM dba_scheduler_job_log
3 WHERE owner = 'OWNER' AND job_name = 'TESTJ'
4 ORDER BY log_date DESC
5 FETCH FIRST 10 ROWS ONLY;
OWNER JOB_N CR DE LOG_DATE STATUS ADDITIONAL_INFO
---------- ----- -- -- ----------------------------------- -------------------- --------------------
OWNER TESTJ 10-FEB-26 12.27.12.302032 PM +00:00 REASON="Job creator: JAVIER_DBA dropped"
OWNER TESTJ 10-FEB-26 12.26.12.111959 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.25.12.104406 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.24.13.100109 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.23.12.904160 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.22.12.711332 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.21.12.504966 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.20.12.494228 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.19.12.292930 PM +00:00 SUCCEEDED
OWNER TESTJ 10-FEB-26 12.18.12.289176 PM +00:00 SUCCEEDED
10 rows selected.
SQL> SELECT owner, job_name, job_creator, enabled, state
2 FROM dba_scheduler_jobs
3 WHERE owner = 'OWNER' AND job_name = 'TESTJ';
OWNER JOB_N JOB_CREATOR ENABL STATE
---------- ----- -------------------- ----- ---------------
OWNER TESTJ JAVIER_DBA FALSE BROKEN
Buenas prácticas
Este problema, cuando aparece, suele venir por una mala praxis de costumbre: Que sean los DBAs los responsables de crear jobs bajo esquemas de usuario.
Aquí las prevenciones deberían ir en la línea de:
- Definir un usuario estable para planificaciones (llámalo PLANNER / JOB_PLANNER / o similar). Al crear una cuenta estable, gestionada como cualquier service account (rotación de password, control de acceso, auditoría), y con los mínimos privilegios necesarios para administrar Scheduler en los esquemas donde aplique (bastaría con CREATE ANY JOB).
- Que sean los usuarios que necesiten crear jobs, que los creen bajo su propio esquema, de forma que OWNER y JOB_CREATOR sean siempre el mismo. No está mal darles la formación necesaria para que manejen el planificador y cada usuario se encargue de sus propios jobs, siempre que sean de su ámbito de aplicación (no jobs de backup, por ejemplo).
- Chequear dependencias antes de borrar un usuario con altos privilegios.
Para este tercer punto, estas consultas nos pueden ir bien:
SQL> variable usuario varchar2(40) SQL> variable usuario varchar2(10) SQL> exec :usuario:='JAVIER_DBA'; PL/SQL procedure successfully completed. SQL> SELECT owner, job_name, job_creator, enabled, state 2 FROM dba_scheduler_jobs 3 WHERE job_creator = :usuario; OWNER JOB_N JOB_CREATOR ENABL STATE ---------- ----- -------------------- ----- --------------- OWNER TESTJ JAVIER_DBA FALSE BROKEN
Conclusión
La documentación te da el modelo del Scheduler y sus conceptos, pero no siempre te lo traduce a “operativa de vida real” (offboarding, seguridad, rotación de personal). Y ahí es donde entran los casos como el que Chris Saxon comenta en AskTom y la nota de soporte: cuando desaparece el creator, el job se rompe, y de eso no te advierte nadie.
En este caso, más importante aun que identificar OWNER de un job, para saber si ese usuario es propietario de jobs planificados, también chequear JOB_CREATOR para saber si ha creado jobs bajo otro esquema.
Hay que tener en cuenta que recrear el usuario en este caso no basta para que el job se repare.
Es preciso volver a habilitar el job desde DBMS_SCHEDULER.ENABLE.
SQL> CREATE USER javier_dba IDENTIFIED BY "JD12!!cafeDB34";
User created.
SQL> GRANT CREATE SESSION TO owner, javier_dba;
Grant succeeded.
SQL> GRANT CREATE ANY JOB TO javier_dba;
Grant succeeded.
SQL> BEGIN DBMS_SCHEDULER.ENABLE('OWNER.TESTJ');
2 END;
3 /
PL/SQL procedure successfully completed.
SQL> SELECT owner, job_name, job_creator, enabled, state
2 FROM dba_scheduler_jobs
3 WHERE job_creator = :usuario;
OWNER JOB_N JOB_CREATOR ENABL STATE
---------- ----- -------------------- ----- ---------------
OWNER TESTJ JAVIER_DBA TRUE SCHEDULED
Referencias
- AskTom (Chris Saxon): caso con
REASON="Job creator ... dropped"
https://asktom.oracle.com/ords/f?p=100:11:0::::P11_QUESTION_ID:9537363000346826584 - Documentación Oracle Scheduler (visión general y administración en versiones modernas):
https://docs.oracle.com/en/database/oracle/oracle-database/21/admin/scheduling-jobs-with-oracle-scheduler.html