TL;DR

Yes. datapatch -local_inventory can be used in RAC, provided every node has exactly the same Oracle Home patch level.

The -local_inventory option bypasses DBMS_QOPATCH and reads the Oracle Home inventory directly using opatch. While this is perfectly safe for single-instance databases, it skips the cluster-wide inventory validation that DBMS_QOPATCH performs in RAC. If one node is patched differently from the others, -local_inventory won’t detect it, and Datapatch will assume the local node represents the entire cluster.

One of Datapatch’s biggest strengths is that it automatically determines which SQL patch actions need to be performed. That’s the magic of Datapatch, it almost always knows exactly what to do.

To make that decision, Datapatch compares two sources of information:

  • The SQL patches already applied to the database (DBA_REGISTRY_SQLPATCH)
  • The SQL patches present in the Oracle Home (the Oracle Inventory)

Most of the time this works seamlessly. But sometimes Datapatch suddenly stops with:

Error: prereq checks failed!
verify_queryable_inventory returned ORA-20001: Latest xml inventory is not loaded into table

What happened?

Before deciding which SQL actions to execute, Datapatch needs to read the Oracle Home inventory.

Normally, it retrieves this information through the DBMS_QOPATCH package, which exposes what Oracle calls the Queryable Inventory. Internally, DBMS_QOPATCH invokes OPatch and returns the inventory information through a PL/SQL API.

The internal workings of DBMS_QOPATCH can get fairly technical, but that’s not really the point here. Something prevented Datapatch from reading the inventory.

Ideally, you should investigate the root cause, open an SR if necessary, and fix the underlying issue. That’s the right long-term solution, and perhaps a topic for another post.

But what if you simply need a way forward?

The easiest workaround

Fortunately, Datapatch provides one:

datapatch -local_inventory

What does -local_inventory do?

Instead of retrieving inventory information through DBMS_QOPATCH, Datapatch calls opatch lsinventory directly from the operating system.

In other words, it completely bypasses the database-side Queryable Inventory.

Since the Oracle Inventory belongs to the Oracle Home rather than the database, this often works perfectly well.

Well… almost.

Why does Datapatch use DBMS_QOPATCH at all?

For a single-instance database, using the local Oracle Home inventory and using DBMS_QOPATCH produce the same result.

For example:

SQL> set long 1000
SQL> set pagesize 1000

SQL> select dbms_qopatch.get_pending_activity from dual;

GET_PENDING_ACTIVITY

<activityRoot>
  <p33239276>
    <patchUId>24468932</patchUId>
  </p33239276>
  <p33231111>
    <patchUId>99999</patchUId>
  </p33231111>
</activityRoot>

This tells us that SQL patches 33239276 and 33231111 are present in the Oracle Home.

In a single-instance environment, this is all Datapatch needs to know.

Why is RAC different?

Things become much more interesting in RAC.

DBMS_QOPATCH doesn’t just inspect the local Oracle Home, it queries every node in the cluster.

If every node has the same SQL patches installed, the output looks exactly like the single-instance example:

<activityRoot>
  <p33239276>
    <patchUId>24468932</patchUId>
  </p33239276>
  <p33231111>
    <patchUId>99999</patchUId>
  </p33231111>
</activityRoot>

This means both patches are installed on every node.

However, if patch levels differ between nodes, the output changes.

For example:

<activityRoot>
  <p33239276>
    <nodeName>node1</nodeName>
    <patchUId>24468932</patchUId>
  </p33239276>

  <p33239276>
    <nodeName>node2</nodeName>
    <patchUId>24468932</patchUId>
  </p33239276>

  <p33231111>
    <patchUId>99999</patchUId>
  </p33231111>
</activityRoot>

This output is often misunderstood.

When a SQL patch is installed on every node, DBMS_QOPATCH returns a single entry for that patch, with no nodeName element.

When a patch is missing from one or more nodes, the behavior changes: DBMS_QOPATCH repeats the patch entry once for each node where the patch is missing, adding a nodeName element that identifies that node.

In the example above:

  • Patch 33231111 is installed on every node, so it appears only once and has no nodeName.
  • Patch 33239276 is missing from node1 and node2, so the <p33239276> element appears twice: once for each missing node.

This is why the function is named GET_PENDING_ACTIVITY: it reports SQL patches whose rollout is still pending somewhere in the cluster.

At this point, Datapatch cannot determine the intended state of the cluster.

Is the patch still being rolled out to the remaining nodes?

Or is it actually being rolled back from the nodes where it is currently installed?

Because it cannot safely answer that question, Datapatch intentionally takes no action for those patches.

So, can we use -local_inventory in RAC?

Yes.

But only if you’re absolutely certain that every RAC node has the same Oracle Home patch level.

The reason is simple.

With -local_inventory, Datapatch only looks at the Oracle Home on the local node. It never asks the other nodes what they have installed.

It assumes the local Oracle Home accurately represents the entire cluster.

If that assumption is true, everything works as expected.

If it isn’t, Datapatch may make decisions based on incomplete information.

Final recommendation

  • Single instance: ✅ Safe to use -local_inventory.
  • RAC: ✅ Safe only if every node has identical Oracle Home patch levels.
  • Mixed patch levels in RAC: ❌ Don’t use -local_inventory. Fix the cluster consistency first or resolve the DBMS_QOPATCH issue.

-local_inventory is a very useful escape hatch when the Queryable Inventory isn’t working. Just remember what you’re giving up: the cluster-wide validation that DBMS_QOPATCH performs. As long as you know every RAC node is patched identically, it’s a perfectly valid option.

Leave a Reply

About THIS SITE

I write about Oracle databases, with a focus on Data Pump, patching, and upgrades.

This site is a collection of things that are easy to get wrong, hard to understand, or not well explained. Most posts come from real issues I have run into while working with Oracle systems.

If you have ever hit a Data Pump error and had no idea what it meant, you are in the right place.

Discover more from Eventually Stable

Subscribe now to keep reading and get access to the full archive.

Continue reading