I'm maintaining some stored procedures in an Oracle 11g RAC environment that are part of the pipeline of steps for data-interchange with other systems. One in particular has been producing duplicate records. Files get loaded into a set of staging-tables by an ETL job, which then calls this stored procedure, which has no parameters (except an OUT parameter that gets ignored by the calling ETL code, but that's another issue). The body of the procedure starts with a statement like
For I in ( SELECT * from SOME_STAGING_TABLE where status = 'NEW' order by X_ID) LOOP
However, the ETL job that calls this is in turn called by another ETL job that finds all "files" that haven't been processed and calls it, once per file, in parallel. I think what's happening is:
- Master ETL job runs, finds two files, invokes two worker jobs
- Worker ETL job A runs, gets through first phase
- Worker ETL job B runs, gets through first phase
- Worker ETL job A invokes stored procedure
- Stored procedure A' gets two files' worth of records to process
- Worker ETL job B invokes stored procedure
- Stored procedure B' gets two files' worth of records to process
One solution might be to enforce serialization in the ETL service. Another might be to change the calling-convention of the stored procedure so it takes a file ID as a parmeter. However, let's say I need to do it in the database. Is there any way to set up a stored procedure so that only one connection can be executing a designated block of code inside it at a time?
(In C or Java this would be called a "mutex" or "synchronized block", and I know MySQL has a "LOCK TABLES" statement that could be used for that purpose; does Oracle 11g have anything like that?)
Best Answer
Oracle has several locking mechanisms that you can use to serialize operations:
DBMS_LOCK.request
. This lock can be maintained for the duration of the session or until you callDBMS_LOCK.release
. This lock can be maintained across commits.Example of serialization using
DBMS_LOCK
:Only one session can run this procedure at the same time: