A few days ago I received an email from a subscriber. The question looked simple… but it came with a twist:

Good morning Javier, 
I have two database users: 
1. OWNER 
2. DBA 

DBA creates a job where the owner is user OWNER.
The job runs without issues.
The user DBA is dropped.

Tricky question:  What happens with this job?
1) It runs? 
2) It Fails?
Why? 

The “automatic” answer many of us would give (me included) is: if the job “belongs to” OWNER and OWNER still exists, then it should keep running.

But Oracle Scheduler stores more information than we typically look at out of habit… and that’s exactly where the surprises show up.

Only checking the OWNER column: professional reflex

I’m the first one guilty of this.

I always go straight to OWNER to know who owns an object. A table might be owned by one user while its index ends up owned by SYSTEM (if a DBA created it, it can happen), or you might be checking who owns a DB link, a synonym, and so on.

So OWNER becomes the default reference column. But in Scheduler there is another concept that often goes unnoticed: the user who created the job.

When the creator and the owner are the same, there’s usually no big problem. Even when jobs are created by SYS or SYSTEM, you can assume the creator will always exist. But here we care about a very specific scenario: when OWNER and JOB_CREATOR are different.

This happens, for example, when a DBA (or a user with privileges such as CREATE ANY JOB) creates jobs “on behalf of” another schema.

What does the documentation say… and what does it omit?

Oracle’s Scheduler documentation explains the model, privileges, and objects (jobs, programs, schedules, chains), and makes it clear there are multiple ways to manage jobs.

But it usually does so from a “functional” point of view: it talks about creating jobs, enabling/disabling them, monitoring them, etc. What it doesn’t really cover are best-practice recommendations, nor does it warn you about collateral effects of offboarding (when a person’s account is removed due to security policy).

And that’s exactly what I miss in the documentation: a note or warning that says something like:

  • “If you run DROP USER on the creator, even if the owner still exists, the job becomes BROKEN.”

AskTom and Oracle Support

Apparently, this didn’t happen only to this subscriber, and it’s not a theoretical paranoia. It has happened to more than one person and you can see it as a real case on AskTom (Chris Saxon): when the creator is removed (DROP USER), some jobs end up broken. And in the job log you can see an explicit reason:

  • REASON="Job creator: <usuario> dropped"

Reference (AskTom):
https://asktom.oracle.com/ords/f?p=100:11:0::::P11_QUESTION_ID:9537363000346826584

There is also a support note that corroborates this behavior (in the sense of “this can happen and there is an explanation”). In my opinion, though, this is something we should be reading in the public documentation—not discovering through support after jobs suddenly become broken while the OWNER itself has not changed.

In other words, in many teams the problem is discovered when the job fails.

And you need to be careful, because recreating the ‘creator’ user does not automatically fix the problem.

Lab

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.

-- FROM ANOTHER TERM, AS SYS or DBA user
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


-- CAUTION! In DBA_SCHEDULER_JOB_LOG there is no column about JOB_CREATOR, neither CREDENTIAL_OWNER or DESTINATION_OWNER.


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

Best practices

When this problem shows up, it often comes from a bad habit: having DBAs create jobs under application/user schemas.

Prevention should go in this direction:

  1. Define a stable scheduling user (call it PLANNER / JOB_PLANNER / or similar). Make it a service account managed like any other (password rotation, access control, auditing), and grant only the minimum privileges needed to administer Scheduler where it applies (typically CREATE ANY JOB is enough).
  2. Have the users who need to create jobs create them under their own schema, so that OWNER and JOB_CREATOR are always the same. It’s not a bad idea to train them to use Scheduler so each team owns its own application jobs (not backup jobs, for example).
  3. Check dependencies before dropping a highly privileged user.

For that third point, these queries are helpful:

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

Conclusion

The documentation gives you the Scheduler model and its concepts, but it doesn’t always translate them into “real-life operations” (offboarding, security, staff rotation). That’s where cases like the one Chris Saxon discusses on AskTom and the support note come in: when the creator disappears, the job breaks—and nobody warns you clearly enough.

In this scenario, it’s not only important to identify the OWNER of scheduled jobs, but also to check JOB_CREATOR to find out whether that user created jobs under someone else’s schema.

And keep in mind: recreating the user is not enough to “repair” the job automatically. You need to re-enable it:

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

References

Share This