Every night, hundreds of batch programs process millions of rows to keep the retail machine running. Understanding the batch engine is essential for every RMS developer.
What is the RMS Batch?
During business hours, RMS processes individual transactions — a buyer creates a purchase order, a price analyst submits a price change, a store receives a shipment. But many critical operations cannot happen in real-time because they affect millions of rows or require complex calculations across the entire dataset.
These operations run as batch programs during the overnight batch window (typically 10 PM – 6 AM):
A typical large retailer has 200-400 batch programs running in sequence and parallel during the nightly window.
Pro*C: The Batch Language
Most RMS batch programs are written in Pro*C — a C programming language with embedded SQL. Oracle's Pro*C precompiler converts the embedded SQL into Oracle Call Interface (OCI) function calls, which are then compiled with a standard C compiler.
Why Pro*C?
- Performance: C programs execute 2-5x faster than equivalent PL/SQL for heavy data processing
- Memory Control: C gives direct control over memory allocation, buffer sizes, and data structures
- OS Integration: C programs can interact with the file system (read/write flat files), environment variables, and OS utilities
- Array Processing: Pro*C supports array fetch and array insert, processing thousands of rows per database round trip
Pro*C Compilation Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Source File │────▶│ Pro*C │────▶│ C Compiler │────▶│ Executable │
│ (.pc) │ │ Precompiler│ │ (gcc/cc) │ │ (binary) │
│ │ │ (proc) │ │ │ │ │
│ C code + │ │ Converts │ │ Compiles │ │ Ready to │
│ embedded │ │ SQL to │ │ pure C │ │ run │
│ SQL │ │ OCI calls │ │ to binary │ │ │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Pro*C vs. PL/SQL Batch
| Aspect | Pro*C | PL/SQL |
|---|---|---|
| Performance | Faster (compiled C) | Slower (interpreted PL/SQL) |
| File I/O | Native file system access | Requires UTL_FILE or directory objects |
| Memory | Manual control (malloc/free) | Automatic (PGA management) |
| Debugging | Difficult (C debugger, log files) | Easier (DBMS_OUTPUT, exception handling) |
| Maintenance | Complex (recompile on DB changes) | Simpler (no recompilation needed) |
| Cloud Compatible | ❌ Not in SaaS (no OS access) | ✅ Runs in Autonomous DB |
The Nightly Batch Flow
The nightly batch runs in a defined sequence, with some programs running serially and others in parallel:
10:00 PM ─── FOUNDATION BATCHES ──────────────────────────────
│
├── vdate_job (advance business date)
├── currrate_load (load currency rates)
└── fiscal_date_update (calendar updates)
11:00 PM ─── PRICING BATCHES ──────────────────────────────────
│
├── price_change_execute (execute price changes)
├── clearance_execute (execute clearance markdowns)
└── promotion_execute (activate promotions)
12:00 AM ─── SALES PROCESSING ──────────────────────────────────
│
├── saposupld (post sales from ReSA to RMS)
└── stock_ledger_post (update stock ledger)
1:00 AM ─── INVENTORY BATCHES (PARALLEL) ──────────────────────
│
├── Thread 1: wac_calc (recalculate WAC)
├── Thread 2: inv_adj_post (post adjustments)
└── Thread 3: stock_count_post (post count results)
2:00 AM ─── REPLENISHMENT (PARALLEL) ──────────────────────────
│
├── Thread 1-8: replenish (calculate reorder qtys)
└── auto_po_create (generate automatic POs)
4:00 AM ─── DATA EXTRACTION ──────────────────────────────────
│
├── fdl_item_extract (items for downstream)
├── fdl_itemloc_extract (item-loc for downstream)
└── fdl_inv_extract (inventory for downstream)
6:00 AM ─── BATCH COMPLETE ────────────────────────────────────
Threading & Parallel Execution
Many RMS batch programs support multi-threading — splitting the workload across multiple parallel processes:
How Threading Works
- The scheduler launches the batch program with a thread count parameter (e.g.,
replenish -threads 8) - The program reads the
RESTART_CONTROLtable to determine its assigned data range - Each thread processes a non-overlapping subset of the data (typically partitioned by department, location, or item range)
- Threads run independently — if Thread 3 fails, Threads 1, 2, 4-8 continue
- After all threads complete, a final "consolidation" step merges results
Thread Assignment Example
For the replenishment batch with 8 threads across 80 departments:
| Thread | Departments Assigned |
|---|---|
| Thread 1 | Depts 1000-1009 |
| Thread 2 | Depts 1010-1019 |
| Thread 3 | Depts 1020-1029 |
| ... | ... |
| Thread 8 | Depts 1070-1079 |
RESTART_CONTROL Table
The RESTART_CONTROL table is a critical infrastructure table that manages batch program threading and restart capability:
| Column | Type | Description |
|---|---|---|
PROGRAM_NAMEPK | Program ID | The name of the batch program (e.g., 'REPLENISH', 'PRICE_CHANGE_EXECUTE'). |
THREAD_NOPK | Thread Number | The thread number (0 for single-threaded programs, 1-N for multi-threaded). |
NUM_THREADS | Total Threads | Total number of threads configured for this program. |
STATUS | Execution Status | Current status: 'S' (Started), 'C' (Completed), 'F' (Failed), 'W' (Waiting). |
START_DATETIME | Start Time | When this thread started execution. |
END_DATETIME | End Time | When this thread completed (or failed). |
RESTART_BOOKMARK | Restart Position | The last successfully processed record identifier. If the program fails and is restarted, it resumes from this bookmark instead of starting over. |
Error Handling & Recovery
When a batch program encounters an error:
- The program writes the error to its log file (
.log) and optionally to a bad file (.bad) - The program updates RESTART_CONTROL with status = 'F' (Failed) and sets the restart_bookmark
- The scheduler detects the failure and holds all dependent downstream programs
- Operations team investigates the log file to determine the root cause
- After fixing the issue, operations restarts the program — it picks up from the restart_bookmark
Common Error Types
| Error | Typical Cause | Fix |
|---|---|---|
ORA-00001: unique constraint | Duplicate data in source | Identify and remove duplicate, then restart |
ORA-01555: snapshot too old | Long-running query exhausted undo | Increase UNDO_RETENTION, reduce commit interval |
ORA-04031: shared pool exhausted | Too many unique SQL statements | Fix literal SQL, enable cursor_sharing |
ORA-01652: unable to extend temp | Large sort/hash join exceeded temp space | Increase TEMP tablespace or optimize query |
Segmentation fault | Pro*C memory corruption | Check array sizes, buffer overflows in C code |
Batch Scheduling (POM & External)
On-Premise: External Schedulers
In on-premise deployments, batch programs are orchestrated by external schedulers:
- Control-M — the most common enterprise scheduler for Oracle Retail
- Autosys — popular in financial services
- cron — used in smaller deployments
Cloud: POM
In Oracle Retail Cloud, POM (Process Orchestration and Monitoring) is the mandatory scheduler. It provides a web-based interface for defining batch flows, dependencies, and monitoring execution.
Monitoring & Troubleshooting
Log File Analysis
Every batch program produces a log file. Key things to search for:
- "ORA-" — Oracle database errors
- "ERROR" — Application-level errors
- "ROWS PROCESSED" — Data volume indicators
- "ELAPSED TIME" — Performance benchmarks
- "RESTART" — Restart bookmark information
Batch Duration Trending
Track batch duration over time. A batch program that normally runs in 30 minutes but suddenly takes 2 hours indicates:
- Stale statistics on the tables it queries
- Data volume growth (more rows to process)
- Lock contention from a concurrent process
- Infrastructure issue (slow I/O, reduced CPU)
Important Gotchas
- !Never kill a running batch program with
kill -9. This leaves RESTART_CONTROL in an inconsistent state and can leave database locks orphaned. Usekill -15(graceful termination) and wait for the program to clean up. - !If a batch program fails, always check the
.badfile (if one exists) before restarting. The bad file contains the specific rows that caused the failure — fixing the data issue before restart prevents the same failure from recurring. - !Pro*C batch programs must be recompiled whenever the database schema changes (e.g., after an Oracle patch that modifies table structures). Running old binaries against a modified schema causes unpredictable failures.
- !The batch window is finite. If replenishment takes too long and overlaps with store opening, stores may not have today's replenishment orders. Optimize the longest-running batches first.
Key Takeaways
- RMS batch programs are primarily written in Pro*C (C with embedded SQL) for maximum performance on million-row operations.
- The nightly batch follows a defined sequence: foundation → pricing → sales → inventory → replenishment → data extraction.
- Multi-threading splits workload across parallel processes, with each thread processing a non-overlapping data range.
- RESTART_CONTROL tracks each program's status and restart bookmark, enabling recovery without reprocessing already-completed work.
- POM replaces external schedulers (Control-M, Autosys) in cloud deployments for batch orchestration and monitoring.
- Always check log and .bad files before restarting a failed batch program — fix the root cause first to prevent recurring failures.


