Feed aggregator

Azure Bootcamp Switzerland 2026 edition

Yann Neuhaus - 4 hours 25 min ago

Today I attended the Azure Bootcamp Switzerland event in Bern. Here is a summary of what I saw and what I learned in the sessions.

The opening keynote was about Azure Sovereign Architecture where the presenter gave us an update on the current Azure/Microsoft projects. We also had an explanation on how sovereignty works.

Then I joined a session titled “Time Bombs In Entra ID – How Well Are Your Entra ID Apps Managed?”. The speaker explained to us how Azure App registration and service principal really work. He also gave us some advice on best practices when using this kind of Azure/Entra resource.

Before the lunch break I joined a session on how some architects resolved the “multiple teams needed to deploy something” problem. They automated the deployment with CI/CD and Terragrunt. They did a demo on how they use their code and how they make infrastructure changes with it.

After the lunch, I chose to go in a more network oriented presentation. The topic was how to get rid of VPN by using an Azure service called Global Secure Access. Even though I’m not convinced that we can get rid of VPNs, this option could be something for highly Microsoft infrastructure as it uses the Microsoft backbone for all the network routing.

The last two sessions I attended sessions on Azure Policy. The topics were first using code to deploy Azure policies, as it’s a better way to have them identical in multiple environments and as it as also faster than using the Azure interface, which is slow. The second one was about using conditional access as safer alternative for securing Azure tenants with policies. This method is quite interesting but requires a paid version of Entra to be activated.

Finally, for the closing keynote, we had a presentation about an application developed by a Swiss company that helps emergency services coordinate. It’s allowing call centers to locate and contact closest to scene savers and organize their deployment.

Once again, I’m glad that could attend this event. I learned quite a bunch of things and could also refresh my memory on some other topics. The sessions are long enough to detail a topic and the speakers are always performing well.

L’article Azure Bootcamp Switzerland 2026 edition est apparu en premier sur dbi Blog.

Reduce downtime when refreshing your non-production databases using Multitenant

Yann Neuhaus - 14 hours 10 min ago
Introduction

You probably refresh your non-production Oracle databases with production data from time to time or on a regular basis. Without Multitenant, the most common procedure to do this refresh is a DUPLICATE FROM BACKUP with RMAN. The drawback is the unavailability of the database being refreshed during the DUPLICATE. You first need to remove the old version of the database, then start the DUPLICATE and wait until it’s finished. If you have Enterprise Edition and enough CPU, you can lower the time needed for the refresh by allocating a sufficient number of channels. But with a small number of CPU (which is normal for a non-production server), or eventually with Standard Edition (single channel RMAN operations only), a multi-TB database refresh can take several hours to complete. And if it fails for some reasons, you need to retry the refresh, extending even more the downtime.

Multitenant brought new possibilities for refreshing a database, and my favorite one is a CREATE PLUGGABLE DATABASE from a database link (DB link). It’s dead easy compared to a DUPLICATE FROM BACKUP on a non-CDB database. And you can lower the downtime to the very minimum. Here is how I did this for several projects.

How to lower the downtime to the minimum when refreshing a non-production PDB?

You probably know that one of the advantage of a pluggable database is the easiness of changing its name. You just need to stop the PDB, rename it, and restart it. You can then use this technique to refresh a PDB under a temporary name and let the actual PDB available during the refresh. Once the refresh is finished, drop or rename the actual PDB, and rename the newest one to its target name. Even if your refresh takes hours, your downtime is limited to a couple of seconds/minutes.

Step 1: add an additional grant for source PDB’s administrator

The PDB administrator on the source database must have the CREATE PLUGGABLE DATABASE privilege:

ssh oracle@p01-srv-ora
. oraenv <<< P19PMT
sqlplus / as sysdba
Alter session set container=P19_ERP;
grant create pluggable database to SYSERP;
exit
Step 2 : add a TNS entry on the target server

The target server must have a TNS entry to the source PDB (production). If your source PDB and its container are protected by a Data Guard configuration, dont’t forget to add both addresses:

ssh root@t01-srv-ora
su – oracle
. oraenv <<< D19PMT
vi $ORACLE_HOME/network/admin/tnsnames.ora
…
P19_ERP =
(DESCRIPTION =
   (LOAD_BALANCE = OFF)
   (FAILOVER = ON)
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = p01-srv-ora)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = p02-srv-ora)(PORT = 1521))
   )
   (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = P19_ERP)
   )
)

tnsping P19_ERP
…
Step 3 : create a DB link on the target container

A DB link is required on the target container:

ssh root@t01-srv-ora
su – oracle
. oraenv <<< D19PMT
sqlplus / as sysdba
CREATE DATABASE LINK P19_ERP CONNECT TO SYSERP IDENTIFIED BY "*************"  USING 'P19_ERP';

select count(*) from dual@P19_ERP;
  COUNT(*)
----------
         1
exit
Step 4 : prepare the scripts for the refresh

Basically, refresh will have 5 main tasks:

  • create a new PDB with a temporary name _NEW on the target container from the source PDB
  • start the new PDB for its correct registration in the container
  • run an optional script for modifying production data (masking, disabling tasks, …)
  • stop and rename the current PDB to _OLD, then start it again
  • stop and rename the new PDB to its target name and start it again

Task 2 is needed because you cannot rename a PDB immediately after creation. You first need to open it, then close it for being able to change its name.

Let’s create 2 scripts on the target server, one shell script and one SQL script:

vi /home/oracle/scripts/refresh_D19_ERP.sh
#!/bin/bash
export ORACLE_SID=D19PMT
export REFRESH_LOG=/home/oracle/scripts/log/refresh_D19_ERP_`date +%d_%m_%Y-%H_%M_%S`.log
export ORACLE_HOME=`cat /etc/oratab | grep $ORACLE_SID | awk -F ':' '{print $2;}'`
date >> $REFRESH_LOG
$ORACLE_HOME/bin/sqlplus / as sysdba @/home/oracle/scripts/refresh_D19_ERP.sql >> $REFRESH_LOG
date >> $REFRESH_LOG
exit 0

vi /home/oracle/scripts/refresh_D19_ERP.sql
set timing on
show pdbs
alter pluggable database D19_ERP_OLD close immediate;
Drop pluggable database D19_ERP_OLD including datafiles;
show pdbs
create pluggable database D19_ERP_NEW from P19_ERP@P19_ERP ;
show pdbs
alter pluggable database D19_ERP_NEW open;
show pdbs
alter session set container=D19_ERP_NEW;
@/home/oracle/scripts/post_refresh_D19_ERP.sql 
alter session set container=CDB$ROOT;
alter pluggable database D19_ERP close immediate;
alter pluggable database D19_ERP rename global_name to D19_ERP_OLD;
alter pluggable database D19_ERP_OLD open;
show pdbs
alter pluggable database D19_ERP_NEW close immediate;
alter pluggable database D19_ERP_NEW rename global_name to D19_ERP;
Alter pluggable database D19_ERP open;
Alter pluggable database D19_ERP save state;
show pdbs
exit

It does the job, although these are very basic scripts: further controls could be added to trap errors, manage services, and so on.

Step 5 : schedule the refresh

Scheduling can be done through the crontab, for example every evening at 11.30PM:

crontab -l | grep D19_ERP | grep refresh
30 23 * * * sh /home/oracle/scripts/refresh_D19_ERP.sh
Conclusion

This is definitely a smart solution as soon as you have enough space on disk to have 2 copies of the PDB. It’s quite reliable and ticks all the boxes where I deployed these scripts.

L’article Reduce downtime when refreshing your non-production databases using Multitenant est apparu en premier sur dbi Blog.

OGG-08502 Path not found error from OGG Receiver Service

Yann Neuhaus - 17 hours 27 min ago

Recently, after a successful migration to GoldenGate 26ai, a customer complained that he was seeing a lot of the following error in the ggserr.log file of a GoldenGate deployment (I replaced the names for the purpose of this blog).

2026-05-18T14:32:35.948+0200  ERROR   OGG-08502. Oracle GoldenGate Receiver Service for Oracle:   Path path21 not found.

More precisely, in that case, path21 is a distribution path sending trail files from deployment ogg_test_02 to ogg_test_01. And the error shown above appeared in the log file of the ogg_test_01 deployment.

While this error did not seem to indicate any operational issue in the replication, after checking on multiple environments, I confirmed that it appears everywhere. So what is happening exactly ?

If you get this error and do not know where it comes from, log in to the web UI of the affected deployment, and go to the Receiver Service Paths tab. You should see a list of the distribution paths that are connecting to your deployments. The example below shows the path21 that is mentioned in the error.

How to reproduce the error ?

If you click on this path… Nothing happens ! And by “nothing”, I mean “nothing abnormal”. In fact, the statistics are properly displayed (see below), and there is no error shown to the user. However, if you look at your ggserr.log file you will see that the error given above appears.

At first glance, this might not seem like a huge issue, because if you don’t click on the receiver path, you will not get the error. However, in the log file of the customer, the error appeared regularly. Every minute, to be precise.

Why do I get this error even when I’m not accessing the web UI ?

Luckily, when debugging this issue, I started by putting the target in a blackout in the Oracle Enterprise Manager. To my surprise, the error was gone during the blackout and reappeared right after.

In this case, the Enterprise Manager Plug-in for Oracle GoldenGate is monitoring the status of the deployment every minute and generates the error in the process.

When looking at the targets in the OEM, there is no error. Again, no operational impact.

Does it depend on the way you create the distribution path ?

GoldenGate offers multiple ways of managing deployments : REST API, adminclient, or the web UI. Unfortunately, some bugs (and some features…) mean that you should avoid managing some objects with some of these tools (read why you shouldn’t create profiles through the adminclient, for instance).

In this specific case, all distribution path creation methods lead to the same error in the log file. It doesn’t matter whether you create the distribution path with the adminclient, the REST API or the web UI. They will all lead to this error.

Advanced – What’s happening exactly ?

Let’s dig a bit to see what is happening behind the scenes. By looking at the restapi.log file (read my blog on how to analyze REST API logs efficiently), we can see the full error:

2026-05-18 09:08:58.402+0000 ERROR|RestAPI.recvsrvr | Request #9: {
     "context": {
         "httpContextKey": 140097141801744,
         "verbId": 2,
         "verb": "GET",
         "originalVerb": "GET",
         "uri": "/services/v2/targets/path21",
         "protocol": "http",
         "headers": {
             ...
         },
         "host": "vmogg",
         "securityEnabled": false,
         "authorization": {
             "authUserName": "ogg",
             "authUserRole": "Security",
             "authMode": "Cookie"
         },
         "requestId": 8,
         "uriTemplate": "/services/{version}/targets/{path}",
         "catalogUriTemplate": "/services/{version}/metadata-catalog/path"
     },
     "isScaRequest": true,
     "content": null,
     "parameters": {
         "uri": {
             "path": "path21",
             "version": "v2"
         },
         "query": {
             "WindowRef": "%2Fservices%2Fv2%2Fcontent%2F%23%2FrecvsrvrPaths%2Fpath21%2FpathNetworkStats"
         }
     }
 }
 Response: {
     "context": {
         ...
     },
     "isScaResponse": true,
     "content": {
         "$schema": "api:standardResponse",
         "links": [
             {
                 "rel": "canonical",
                 "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets/path21",
                 "mediaType": "application/json"
             },
             {
                 "rel": "self",
                 "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets/path21",
                 "mediaType": "application/json"
             }
         ],
         "messages": [
             {
                 "$schema": "ogg:message",
                 "title": "Path path21 not found",
                 "code": "OGG-08502",
                 "severity": "ERROR",
                 "issued": "2026-05-18T09:08:58Z",
                 "type": "https://www.rfc-editor.org/rfc/rfc9110.html#name-status-codes"
             }
         ]
     }
 }

The issue comes from the following endpoint : /services/v2/targets/path21. It is described in the documentation under Retrieve an existing Oracle GoldenGate Collector Path. But looking at another endpoint described in Get a list of distribution paths, we get the following response:

{
    "$schema": "api:standardResponse",
    "links": [
        {
            "rel": "canonical",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets",
            "mediaType": "text/html"
        },
        {
            "rel": "self",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets",
            "mediaType": "text/html"
        },
        {
            "rel": "describedby",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/metadata-catalog/targets",
            "mediaType": "application/schema+json"
        }
    ],
    "messages": [],
    "response": {
        "$schema": "ogg:collection",
        "items": [
            {
                "links": [
                    {
                        "rel": "parent",
                        "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets",
                        "mediaType": "application/json"
                    },
                    {
                        "rel": "canonical",
                        "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets/path21_ogg26dist2_7811",
                        "mediaType": "application/json"
                    }
                ],
                "$schema": "ogg:collectionItem",
                "name": "path21",
                "status": "running",
                "targetInitiated": false
            }
        ]
    }
}

Here, we see that the endpoint associated with the path21 object is not recvsrvr/v2/targets/path21 but recvsrvr/v2/targets/path21_ogg26dist2_7811. And looking at this second endpoint, we do not get an error.

{
    "$schema": "api:standardResponse",
    "links": [
        {
            "rel": "canonical",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets/path21_ogg26dist2_7811",
            "mediaType": "text/html"
        },
        {
            "rel": "self",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/targets/path21_ogg26dist2_7811",
            "mediaType": "text/html"
        },
        {
            "rel": "describedby",
            "href": "https://vmogg/services/ogg_test_01/recvsrvr/v2/metadata-catalog/path",
            "mediaType": "application/schema+json"
        }
    ],
    "messages": [],
    "response": {
        "name": "path21",
        "status": "running",
        "$schema": "ogg:distPath",
        "source": {
            "uri": "trail://localhost:7811/services/v2/sources?trail=pdb2/bb"
        },
        "target": {
            "$schema": "ogg:distPathEndpoint",
            "uri": "ws://vmogg/services/v2/targets?trail=pdb2/bb"
        },
        "options": {
            "network": {
                "appOptions": {
                    "appFlushBytes": 27985,
                    "appFlushSecs": 1
                },
                "socketOptions": {
                    "tcpOptions": {
                        "ipDscp": "DEFAULT",
                        "ipTos": "DEFAULT",
                        "tcpNoDelay": false,
                        "tcpQuickAck": true,
                        "tcpCork": false,
                        "tcpSndBuf": 16384,
                        "tcpRcvBuf": 131072
                    }
                }
            }
        }
    }
}

The problem is that it was never decided for path21 to be referred to as path21_ogg26dist2_7811 internally. And it looks like GoldenGate does not know about it either… So until the bug is corrected, you will have to filter this OGG-08502 Path not found error out of the ggserr.log file if you use it for monitoring.

L’article OGG-08502 Path not found error from OGG Receiver Service est apparu en premier sur dbi Blog.

What being an external consultant really changes

Yann Neuhaus - Wed, 2026-05-20 02:01

When people think about consultants, they usually focus on expertise. “They bring experience, frameworks, and best practices.”
That’s true, of course. However, that is not the most impactful aspect of the role.
The real shift happens somewhere less visible: positioning. As an outsider, you don’t just join a team.

You become something different. Over time, I’ve come to think of it as operating within a “shadow team.”

the shadow team

This invisible layer changes how you navigate politics, truth, and influence.
Let’s unpack that.

The “Shadow Team” effect

As an employee, you’re clearly part of the organization.
However, when you’re an external consultant, it’s a different story.
You sit inside delivery teams while remaining outside the organization’s long-term structure. This dual positioning creates what I call a shadow team.

You collaborate closely with internal stakeholders, influence decisions without owning them, and observe dynamics that others are too immersed in to see.

You’re close enough to matter, yet distant enough to stay objective.
This reshapes everything.

Politics: Seeing the system without being trapped in it

Every organization has internal politics, including priorities, power structures, historical tensions, and unwritten rules. The larger the organization, the more politics there are.
Employees must live within that system.
Consultants, on the other hand, can often see the system more clearly because they aren’t fully bound by it.
This doesn’t mean you’re outside of politics, though.
It means:

You can identify misalignments more quickly, notice when decisions are driven by structure, not logic and spot friction between teams that others consider “normal.”

But here’s the key difference:

  • You are less constrained by long-term consequences.
  • An employee may avoid challenging a decision due to its potential impact on their career.
  • However, a consultant can raise the concern because their role is to add clarity, not preserve equilibrium.
  • Still, this doesn’t mean ignoring politics. It means navigating them consciously without being controlled by them.
Neutrality: Your most underrated asset

One of the most powerful—and most fragile—assets of being an external consultant lies in the neutrality that people attribute to you.

You are not:

  • Competing for a promotion
  • Defending a department
  • Protecting past decisions

This creates a rare opportunity. You can become a trusted bridge between stakeholders

When done right, people will:

  • Share concerns they wouldn’t voice internally
  • Ask for your opinion as a “safe” perspective
  • Use you to validate or challenge ideas

However, neutrality is not automatic, it must be earned and can easily be lost.
You lose it when:

  • You align too strongly with one stakeholder
  • You start defending internal logic instead of questioning it
  • You behave like an insider too quickly

The best consultants maintain a delicate balance:

They are close enough to build trust and distant enough to stay credible.

Truth vs. Diplomacy: walking the tightrope

This is where the role becomes truly challenging.
As a consultant, you are often expected to:

  • Tell the truth
  • Challenge assumptions
  • Highlight risks

However, you are also expected to:

  • Maintain relationships
  • Respect stakeholders
  • Keep the project moving forward

These two expectations often conflict with each other.
The naive approach: “Just be brutally honest.”
This approach quickly fails. Brutality destroys trust.

The safe approach: “Say what people want to hear.”
This makes you irrelevant.

The real skill is delivering truth in a way that can be heard.
That means:

  • Frame issues in terms of impact, not fault.
  • Ask questions instead of making accusations.
  • Adapt your message to your audience.

For example, rather than saying, “This process isn’t working at all”

A more measured approach might be: “I see a few risks associated with this process. Could we go over them together?”

The observation is the same.
However, the outcome is different.

What really changes

Being a consultant isn’t just about knowledge. It’s also about positioning. You have a clearer view, speak more freely, and connect across sides.

However, our profession is based on a paradox. We must be objective enough to provide sound advice, yet also be fully committed to the task at hand. Additionally, we must offer honest feedback without hurting the client’s feelings or losing their trust.

At dbi services, we’re passionate about striking that delicate balance, whether the subject is ECM or any other area of our expertise. Learn more about us here.

L’article What being an external consultant really changes est apparu en premier sur dbi Blog.

Instruction-Based Data Analysis with Sparrow and Local LLM

Andrejus Baranovski - Mon, 2026-05-18 06:10
In this video, I show how to use Sparrow instruction processing pipeline to analyze a bond portfolio JSON extracted from a financial document — all running locally, no external APIs.

I run three different analysis cases using Gemma 4 31B on Apple Silicon Mac Mini M4 Pro:

  • Risk classification — categorize each position into low, medium, or high risk based on loss percentage
  • Concentration risk — flag overweight positions above 20% portfolio weighting
  • Portfolio aggregation — total valuation, weighted average P&L, best and worst performer

All three cases use the same sparrow-instructor pipeline, demonstrating how different instruction types — classification, rule-based flagging, and aggregation — are handled by a single local LLM.

Install and configure OEM plug-in for GoldenGate

Yann Neuhaus - Mon, 2026-05-18 01:30

If you are licensed for the GoldenGate Management Pack, using the Enterprise Manager plug-in for GoldenGate improves monitoring and management of your deployments. And after migrating to the Microservices Architecture, you should definitely update your plug-in and rediscover all targets. Let’s see how to do all that here.

In this blog, I will use the latest version of the Enterprise Manager (24ai) and monitor GoldenGate 26ai deployments. The overall workflow is the same for other versions of the Enterprise Manager and GoldenGate, provided OGG is in the Microservices Architecture.

Here are the main steps to monitor GoldenGate targets from the Enterprise Manager:

  • Update the catalog in the Enterprise Manager
  • Deploy the plug-in on the management server
  • Deploy the plug-in on the agent
  • Configure the discovery module
  • Promote the new targets
Checking if the plugin is already installed

Before attempting to install the plug-in, make sure it is not already installed in your environment. To check this, go to Setup > Extensibility > Plug-ins, and expand the Middleware section. If you do not see any line named Oracle GoldenGate, it means the plug-in is not installed yet.

Update the Enterprise Manager catalog

Since most OEM environments do not have access to the Oracle Support directly, we’ll download the plug-in in offline mode. To do so, go to the Setup > Provisioning and Patching > Offline Patching section.

Once in the Offline Patching section, make sure Offline is selected for the connection and download the catalog file as instructed from an environment with access to the Oracle support website. Transfer it to where you have access to the OEM UI, and upload it.

Once the catalog is uploaded, you should see the following information message.

Then, go to Setup > Extensibility > Self Update and click on Check Updates.

You should see the following pop-up appear, with a link from where you will be able to download the OEM Self Update catalog file. For reference, the one I had when writing this blog was the following : https://updates.oracle.com/Orion/Download/download_patch/p9348486_112000_Generic.zip

As instructed, transfer this patch to the OMS host and import it with emcli and the import_update_catalog action. You can also import it from another managed host. It should take around twenty seconds to import everything.

oracle@oem24:~/ [oem24] emcli import_update_catalog -file=/tmp/p9348486_112000_Generic.zip -omslocal
Processing catalog for Diagnostic Tools
Processing update: Diagnostic Tools - AHFFI 25.1.0.1.0 for Linux
Processing update: Diagnostic Tools - AHF 25.5.0.0.0 for HP

[...]

Processing update: Plug-in - GoldenGate Plug-in now supports monitoring of Oracle GoldenGate Microservices, in addition to the Oracle GoldenGate Classic
Processing update: Plug-in - GoldenGate Plug-in now supports monitoring of Oracle GoldenGate Microservices, in addition to the Oracle GoldenGate Classic
Processing update: Plug-in - GoldenGate Plug-in now supports monitoring of Oracle GoldenGate Microservices, in addition to the Oracle GoldenGate Classic
Processing update: Plug-in - GoldenGate Plug-in now supports monitoring of GoldenGate Microservices Architecture, in addition to the GoldenGate Classic Architecture

[...]

Successfully uploaded the Self Update catalog to Enterprise Manager. Use the Self Update Console to view and manage updates.
Time taken for import catalog is 17.289 seconds.
Download GoldenGate plug-in

When this is done, go back to the Self Update page, click on the Plug-In section. You will see the different versions of GoldenGate that are available. When I’m writing this blog, the latest version of the plug-in is 13.5.2.0.0 (the latest patch released in January 2026, 13.5.2.0.6, will be a topic for another blog). Click on the latest version and then on Download.

The following pop-up gives you the link from which you should download the plug-in update file. In my case, it was https://updates.oracle.com/Orion/Services/download/p34651099_112000_Generic.zip?aru=24962501&patch_file=p34651099_112000_Generic.zip.

Once the file is downloaded, import it in the same way as before with the catalog, but this time with the emcli import_update action.

oracle@oem24:~/ [oem24] emcli import_update -omslocal -file=/tmp/p34651099_112000_Generic.zip
Processing update: Plug-in - GoldenGate Plug-in now supports monitoring of Oracle GoldenGate Microservices, in addition to the Oracle GoldenGate Classic
Successfully uploaded the update to Enterprise Manager. Use the Self Update Console to manage this update.

Once this is done, go back to the Setup > Extensibility > Plug-in tab and expand the Middleware section. You should now see Oracle GoldenGate, and 13.5.2.0.0 as the downloaded version.

Deploy the GoldenGate plug-in on the Management Server

Warning : Deploying the plug-in on the management server will temporarily restart OMS components and briefly interrupt monitoring operations. To deploy the plug-in, you have two options:

  • Deploying the plug-in from the web UI.
  • Deploying the plug-in from the CLI.
Deploying the plug-in from the web UI

From the web UI, click on the Oracle GoldenGate plug-in, then on Deploy On, and deploy the plug-in on the Management Servers.

Make sure the correct version of the plug-in is chosen (13.5.2.0.0), and click on Next to run the prerequisite checks.

Once the checks are successfully completed, click on Next.

You should now select the repository credentials for the OEM. You should either use new credentials (if it’s a new environment) or use existing named credentials. Click on Next.

Once everything is done, click on Deploy.

As instructed, you can check the status of the deployment with the emctl status oms -details command.

oracle@oem24:~/ [oem24] emctl status oms
Oracle Enterprise Manager 24ai Release 1
Copyright (c) 1996, 2024 Oracle Corporation.  All rights reserved.
WebTier is Up
Oracle Management Server is Down

This is due to the following plug-ins being deployed on the management server or undeployed from it:
----------------------------------------
Plugin name:    : Oracle GoldenGate
Version:        : 13.5.2.0.0
ID:             : oracle.fmw.gg
----------------------------------------
Deploying the plug-in from the CLI

Alternatively, you can deploy the plug-in with the following command, using the oracle.fmw.gg ID for the plug-in and the latest 13.5.2.0.0 version.

emcli deploy_plugin_on_server -plugin="oracle.fmw.gg:13.5.2.0.0"

Once the plug-in is deployed on the Management Server, you can check again in the web UI : the latest version should be in the On Management Server section.

Deploy the plug-in on the agent

For each GoldenGate host where an OEM agent is running, deploy the plug-in. To do so, from the web UI, click on the Oracle GoldenGate plug-in, then on Deploy On, and select Management Agent.

There is currently a bug with the Supported Target Versions. No matter your patch level, you will not see the latest versions of GoldenGate. Do not worry about this yet. Just make sure 13.5.2.0.0 is selected.

Then, select the agent on which you want to deploy the plug-in.

Let the prerequisite checks run…

And once everything is ready, click on Deploy.

You can check that everything is running properly with the emcli get_plugin_deployment_status command.

Configure GoldenGate monitoring in the Enterprise Manager

Once the plug-in is correctly deployed on the OMS host and on the GoldenGate host agent, you can configure the module. I will only cover the configuration for the Microservices Architecture. Go to the Setup > Add Target > Configure Auto Discovery tab.

Choose the correct agent host, and click on Discovery Modules.

Enable the Oracle GoldenGate Microservices module, click on it, and then on Edit Parameters.

If you deployed GoldenGate with a reverse proxy, set up the plug-in as such.

If you deployed GoldenGate with a port for each service, enter the service manager port (7809, by default).

Warning : if your installation is secured with certificates, make sure to follow the instructions I gave in a blog to avoid EM-90000 errors when discovering new targets.

Once this is done, just go back to the Configure Auto Discovery section, click on the correct host, and then click on Discover Now. Then, go back to the Configure Auto Discovery section. You should now see a greater number of targets in the Discovered targets section.

If the number of targets did not increase, despite a successful discovery, check the blog linked above.

Click on the number of targets to jump to the Auto Discovery Results section. Select the newly discovered Service Manager target, and click on Promote. Once the target is promoted, you should see the new GoldenGate targets being monitored by the Enterprise Manager !

L’article Install and configure OEM plug-in for GoldenGate est apparu en premier sur dbi Blog.

World Password Day and Oracle Security

Pete Finnigan - Fri, 2026-05-15 16:28
I am slightly late with this one as the event itself was on the 7th May 2026. The World Password Day 2026 is a day to try and highlight that passwords are weak. An article I saw on line said....[Read More]

Posted by Pete On 11/05/26 At 12:37 PM

Categories: Security Blogs

Securing Data in Oracle without Cost Options

Pete Finnigan - Fri, 2026-05-15 16:28
I did a presentation at the UKOUG conference at the East Side rooms in Birmingham at the end of 2025. The focus of this talk was to highlight the problem of securing data held in an Oracle database without using....[Read More]

Posted by Pete On 05/05/26 At 11:25 AM

Categories: Security Blogs

Unable to Perform ONLINE DDLs on tables when Supplemental Logging is enabled

Tom Kyte - Fri, 2026-05-15 16:28
Dear Tom, In our ERP, we are actively consuming both EBR & Supplemental Logging. EBR is for upgrades with a near zero downtime while Supplemental Logging is mainly for CDC, LogMiner & GoldenGate. But we encounter errors when ALTER TABLE statements are executed for normal tables in ONLINE mode while Supplemental Logging is enabled. The error we are getting is: <i>ORA-14416: Online DDL's cannot be used with certain types of tables.</i> Quick Test Steps: -- enable minimal supplemental logging (from CDB) <code> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;</code> -- create first table and its constraints <code> CREATE TABLE ORDER_TABLE ( ID VARCHAR2(50), DESCRIPTION VARCHAR2(100), ORDER_DATE DATE, CUSTOMER_ID VARCHAR2(50), CF_ID VARCHAR2(50) ); ALTER TABLE ORDER_TABLE ADD CONSTRAINT ORDER_PK PRIMARY KEY (ID); ALTER TABLE ORDER_TABLE ADD CONSTRAINT ORDER_CFK UNIQUE (CF_ID) USING INDEX; </code> -- create second table and its constraints <code> CREATE TABLE ORDER_CF_TABLE ( CF_ID VARCHAR2(50), AUTH_ID VARCHAR2(100), AUTH_DATE DATE ); ALTER TABLE ORDER_CF_TABLE ADD CONSTRAINT ORDER_CF_PK PRIMARY KEY (CF_ID); ALTER TABLE ORDER_CF_TABLE ADD CONSTRAINT ORDER_CF_RK FOREIGN KEY (CF_ID) REFERENCES ORDER_TABLE (CF_ID) ON DELETE CASCADE; ALTER TABLE ORDER_CF_TABLE ADD CONSTRAINT ORDER_CF_TABLE_CF_ID_NN CHECK ("CF_ID" IS NOT NULL); </code> Now try to execute below: <code>ALTER TABLE ORDER_CF_TABLE DROP CONSTRAINT ORDER_CF_RK KEEP INDEX ONLINE;</code> Error ORA-14416 is raised. Since both ONLINE mode for table DDLs & Supplemental Logging are key functionalities in Oracle database, what we believe is, it should be possible to use them at the same time. Could you please explain this behavior & any possible ways to achieve ONLINE DDLs on tables for upgrades while supplementary logging is enabled? Thanks & Kind Regards, Navinth
Categories: DBA Blogs

Authid current user functionality

Tom Kyte - Fri, 2026-05-15 16:28
Hi Connor, Let me describe the situation. Our client is running a warehouse management system. There are two schemas wh1 and wh2. All the packages and procedures are created in schema wh1 with authid current user. Today I have faced the issue with the SKU master. Both the schemas have the SKU master, which should be ideally identical. When a particular procedure of a package is called from schema wh2 and was looking for an SKU which was present in schema wh2 but was missing from wh1 it flagged an error that the SKU is missing. When I created the SKU in schema wh1 it processed successfully. This is really puzzling. To best of my knowledge when the procedure is being called from schema wh2 it should access schema wh2 tables by default when we are not prefixing the table name with schema name. Am I missing something. Please share your view. Let me try with a sample code: tablename : sku schemas : wh1 and wh2 The said table is created in both the schemas. Lets sku 'SAMPLE1' is in schema wh2. But this sku does not exist in schema wh1. create or replace package wh1.sync_sku is authid current_user; begin upsert_sku(p_sku varchar2); end; create or replace package body wh1.sync_sku is begin procedure upsert_sku(p_sku varchar2) is declare v_found char(1) := 'N'; begin select 'Y' into v_found from sku where sku = p_sku; exception when no_data_found then raise_appliocation_error(-20001, 'SKU does not exist'); when others then raise; end; end; When the procedure upsert_sku is executed from schema wh2 with parameter 'SAMPLE1' its showing the error 'SKU does not exist' although the sku is exist in schema wh2. As soon as we insert the sku in schema wh1 the procedure executes successfully. The schema wh2 have all the required rights to execute the procedure of schema wh1.
Categories: DBA Blogs

segregration of duties template for Oracle Database

Tom Kyte - Fri, 2026-05-15 16:28
Oracle has published following document for MySQL: https://blogs.oracle.com/mysql/why-your-application-should-not-use-one-mysql-user-for-everything. I have not found similar document for Oracle Database: I would like to know if Oracle has documented something similar for Oracle Database ? Thanks.
Categories: DBA Blogs

oracle error 1408 and 6502

Tom Kyte - Fri, 2026-05-15 16:28
how to find which field raise the error 6502 or 1408?
Categories: DBA Blogs

include heading while downloading an interactive report into pdf

Tom Kyte - Fri, 2026-05-15 16:28
hi I have created an interactive report I want to include heading e.g. Amountwise advances as on how can I do this Also I want to include heding while downloading as pdf please help
Categories: DBA Blogs

Index logging

Tom Kyte - Fri, 2026-05-15 16:28
what is the difference between logging and nologging when creating an index
Categories: DBA Blogs

add a new column to table The column will be of type NUMBER(19,0) and nullable (null by default).

Tom Kyte - Fri, 2026-05-15 16:28
My question is if they add the column the table will be block during the coluum add because it's not enteprise but standard edition
Categories: DBA Blogs

Customer case study – automating SQL Server TLS Encryption with Ansible and Certificates (Architecture)

Yann Neuhaus - Fri, 2026-05-15 14:35

When working with SQL Server environments, securing client connections can become an important requirement, especially when TLS encryption must be implemented using certificates. In this context, a customer asked us to develop an Ansible playbook and role to automate the configuration of TLS for SQL Server. The certificates are generated from the customer PKI and provided as PEM files containing the server certificate, the private key, and the certificate chain.

However, some extractions and conversions are required before these certificates can be used on Windows and configured for SQL Server.

Here, the idea is to propose a solution (the architecture) that prepares the certificate, imports it on the SQL Server host, and configures SQL Server to use it.

We will also see how to separate the preparation and activation steps in order to reduce the impact on the SQL Server service.

In this blog post, we will describe the global approach and the Ansible logic used to implement certificate-based TLS encryption for SQL Server.

Implementation logic

Before configuring TLS encryption on SQL Server, the first point was to understand the certificate format provided by the customer PKI.

In our case, the generated file is a <machine>.pem file. This file contains the server certificate used for TLS, the private key and the certificate chain with the intermediate and root certificates.

As this format cannot be directly used as-is on the Windows side for SQL Server, some extraction and conversion steps are required.

The general idea is to use the Ansible control node as a working area.

The PEM file is first copied into a temporary folder where the different parts of the certificate are extracted:

  • the leaf certificate
  • the intermediate certificate
  • the root certificate
  • the private key

These elements are then used to build a PFX file which can be imported on the Windows SQL Server host.

The PFX is installed in the LocalMachine\My certificate store while the intermediate and root certificates are imported into the appropriate Windows certificate stores.

The implementation has been designed around three different execution modes: stage, activate, and full.

The stage mode is used to prepare the certificate without any impact on the SQL Server service. It copies the PEM file, performs the extractions, builds the PFX file, copies it to the managed Windows node and imports the certificates into the Windows certificate stores. No registry change is performed, and the SQL Server service is not restarted. This mode is useful when we want to prepare the server in advance before switching SQL Server to the new certificate.

The activate mode assumes that the certificate is already present on the Windows server. Its role is to configure SQL Server to use the installed certificate and depending on the selected option, restart the SQL Server service or leave the change pending until the next planned reboot.

This can be useful when the certificate activation must be aligned with an existing maintenance window, for example during monthly OS patching.

The full mode executes the complete configuration from end to end. It performs the extraction and conversion steps, imports the certificates, grants the required permissions, configures SQL Server to use the expected certificate, and restarts the SQL Server service only if required. To avoid unnecessary impact, the role relies on the certificate thumbprint. If the expected certificate is already configured, no change is applied and the SQL Server service is not restarted. This behavior is important for idempotency.

For example, if the full mode is executed after an activate mode, nothing should be changed if the certificate is already the correct one. The same logic applies if the playbook is executed by mistake while the certificate has not been renewed.

Another point to manage is the restart of the SQL Server service. SQL Server loads the certificate configuration when the service starts. Therefore, when a new certificate is configured, the change is only effective after a restart of the SQL Server service.

For this reason the role should provide an option to control whether the restart is performed immediately or postponed to the next planned reboot.

We also have to consider DNS aliases. The standard use case is to generate a certificate containing at least the short name and the FQDN of the SQL Server host in the subjectAltName. If DNS aliases are used by client applications, they can also be added to the certificate SAN.

For example:

[alt_names]
DNS.1 = A-WS2022-2.lab.local
DNS.2 = A-WS2022-2

Finally, the customer confirmed that the private key included in the PEM file is not encrypted.

This simplifies the conversion process to PFX, but it also means that the PEM file must be handled carefully during the Ansible execution, especially in temporary folders and during file transfers. With this approach, the role provides a controlled way to prepare, activate, or fully configure TLS encryption for SQL Server while keeping the impact on the SQL Server service under control.

Logical workflow

The complete workflow can be represented as follows:

Architecture summary

The certificate manipulation is performed on the Ansible control node.

The Windows certificate import and SQL Server configuration are performed on the managed Windows SQL Server host.

This separation is useful because the PEM processing and PFX generation are handled with Linux tools such as OpenSSL while the certificate installation, private key permissions, registry configuration and SQL Server restart are handled through Windows modules and PowerShell. The design also supports a controlled deployment approach.

The certificate can first be staged without service impact then activated later during a maintenance window.

The full mode can be used when the complete implementation must be executed in a single run. The use of the certificate thumbprint is important for idempotency. It allows the role to detect whether SQL Server is already configured with the expected certificate and avoids unnecessary service restarts when no change is required.

Remarks

For certain reasons we do not disclose the code of the created role.

Thank you. Amine Haloui

L’article Customer case study – automating SQL Server TLS Encryption with Ansible and Certificates (Architecture) est apparu en premier sur dbi Blog.

How Row Goal shapes your SQL Server query strategy by hunting for pierogis

Yann Neuhaus - Fri, 2026-05-15 06:34
The Wroclaw Connection

SQLDay 2026 took place this week, from May 11th to 13th, in Wroclaw. Among the featured speakers was Erik Darling, who delivered both a main session and a full-day workshop dedicated to SQL Server performance. During his presentations, he emphasized a concept that is not always widely understood, known as the Row Goal.

The purpose of this article is to recap Erik’s key observations and to introduce this topic, which can serve as a powerful lever for query optimization.

A quick culinary detour and why pierogis matter

In order to understand the explanations below, one key concept must be understood: the Pierogi.

Pierogi are filled dumplings made from unleavened dough, popular in Polish cuisine and enjoyed worldwide, with various savory and sweet fillings[1], [2].

To be honest, this has nothing to do with our technical topic, but this dish discovered during this trip is so good that I simply had to include it in this blog.

Filling the aisles and designing our database

In this article, we will use a custom-made database simulating a Polish supermarket selling pierogis. Unfortunately, there aren’t many left, and the product distribution is not uniform. In fact, pierogis account for much less than 1% of the supermarket’s total stock.
Here is the script to create the DB, along with its article reference table and inventory:

USE master;
GO

IF EXISTS (SELECT * FROM sys.databases WHERE name = 'PierogiMart')
    DROP DATABASE PierogiMart;
GO

CREATE DATABASE PierogiMart;
GO

USE PierogiMart;
GO

CREATE TABLE Articles (
    ArticleID INT IDENTITY(1,1) PRIMARY KEY,
    ArticleName VARCHAR(50) NOT NULL,
    Price DECIMAL(10, 2) NOT NULL
);

CREATE TABLE Inventory (
    ReferenceID INT IDENTITY(1,1) PRIMARY KEY,
    ArticleID INT NOT NULL,
    ValidityDate DATETIME NOT NULL,
    Quantity INT NOT NULL,
    CONSTRAINT FK_Article FOREIGN KEY (ArticleID) REFERENCES Articles(ArticleID)
);
GO

INSERT INTO Articles (ArticleName, Price)
VALUES 
('Pierogi', 12.50),
('Pasta', 8.00),
('Sandwich', 6.50),
('Quiche', 9.00);
GO

INSERT INTO Inventory (ArticleID, ValidityDate, Quantity)
SELECT TOP 100000 
    2, 
    DATEADD(DAY, ABS(CHECKSUM(NEWID())) % 365, '2025-01-01'), 
    ABS(CHECKSUM(NEWID())) % 100
FROM sys.all_columns a CROSS JOIN sys.all_columns b;

INSERT INTO Inventory (ArticleID, ValidityDate, Quantity)
SELECT TOP 10000 
    3, 
    DATEADD(DAY, ABS(CHECKSUM(NEWID())) % 365, '2025-01-01'), 
    ABS(CHECKSUM(NEWID())) % 100
FROM sys.all_columns a CROSS JOIN sys.all_columns b;

INSERT INTO Inventory (ArticleID, ValidityDate, Quantity)
SELECT TOP 50000 
    4, 
    DATEADD(DAY, ABS(CHECKSUM(NEWID())) % 365, '2025-01-01'), 
    ABS(CHECKSUM(NEWID())) % 100
FROM sys.all_columns a CROSS JOIN sys.all_columns b;

INSERT INTO Inventory (ArticleID, ValidityDate, Quantity)
SELECT TOP 10 
    1, 
    '2026-12-31', 
    5
FROM sys.all_columns;
GO

We are also including a few indexes to simulate a real-world use case and to support our queries, ensuring we get realistic execution plans:

CREATE NONCLUSTERED INDEX IDX_INV_QUANT ON [dbo].[Inventory] ([Quantity]) include (ArticleID)

CREATE NONCLUSTERED INDEX IDX_INV_VALIDITY on [dbo].[Inventory] ([ValidityDate]) include (ArticleID)

CREATE NONCLUSTERED INDEX IDX_INV_ART on [dbo].[Inventory] (ArticleID)
What exactly is a Row Goal?

Normally, the SQL Server optimizer seeks to minimize the total cost of processing all data for a query. However, if it knows that you only need a specific number of rows (for example, via a TOP, FAST(N), or EXISTS clause), it changes its strategy.

The Row Goal is this specific row target that pushes the optimizer to favor a plan capable of delivering the first few rows as quickly as possible, even if that same plan would be catastrophic for processing the entire table.

TOP(N): Hunting for the best Pierogi

To illustrate the definition above, let’s search for the pierogis with the furthest expiration dates.
Note that the IDX_INV_VALIDITY index supports this query:

SELECT 
    A.ArticleName, 
    A.Price, 
    I.ValidityDate
FROM Articles A
INNER JOIN Inventory I ON A.ArticleID = I.ArticleID
WHERE A.ArticleName = 'Pierogi'
order by I.ValidityDate desc;

SELECT top 10
    A.ArticleName, 
    A.Price, 
    I.ValidityDate
FROM Articles A
INNER JOIN Inventory I ON A.ArticleID = I.ArticleID
WHERE A.ArticleName = 'Pierogi'
order by I.ValidityDate desc

The difference between these two queries is that one requests only the first 10 rows, while the other requests all matching rows. However, this simple distinction is not merely applied when displaying the results; this condition is pushed deeper into the execution plan to influence the choice of operators (Nested Loop, Hash Join, Merge Join) further down the tree.

For the first query, here is the resulting plan:

As we can see, the optimizer chose a Hash Join given the volume of data to be joined. A Hash Match implies that all the data must be read in order to produce the desired result.

For the second query, here is the execution plan:

We can see that this time, the optimizer chose a Nested Loop, which takes each row from the reference table (Inventory) and joins them with the Articles table. This operation can be very time-consuming if a large number of rows must be processed. However, this is where EstimateRowsWithoutRowGoal comes into play. The value of this property is 40’002.5; this means that in a case where a subset of rows was not specifically required, the optimizer would have estimated the number of rows returned by this operator at that value. We can see, however, that the estimation actually used is 10 rows for one execution, a value clearly derived from the TOP(10).

In summary, adding the TOP(10) allowed the optimizer to use a less expensive join for a small amount of data, even though the TOP operator is located at the very end of the execution plan (since a plan is read from right to left).

EXISTS: The search for the first match

As explained previously, the EXISTS clause has a cardinality of 1 because the very first row meeting the internal condition is enough to validate the case. This triggers a Row Goal, as the optimizer must estimate how many rows it will need to read to satisfy (or not) this condition.

Note: In cases where the condition is never met, the optimizer’s plan can become highly inefficient; for full details, see Erik Darling’s blog [here].

We will now observe this behavior with the following query, varying the internal condition of the EXISTS clause by testing one highly selective (discriminant) case and another much less so.

SELECT 
    A.ArticleName, 
    A.Price
FROM Articles A
WHERE not EXISTS (
    SELECT 1/0
    FROM Inventory I 
    WHERE I.ArticleID = A.ArticleID 
    AND I.Quantity > 10 -- vs 98
);

As you may have noticed, I am looking here for products that maintain a certain quantity for every possible consumption date. My goal, of course, is to avoid depleting the stocks of these excellent Polish pierogis so that everyone can enjoy them!

The case where we want to ensure that all existing quantities for an item are greater than 10 is very difficult to satisfy; based on the statistics available to the optimizer, all items have 10 or more units in stock, except for the pierogis!
Since this condition is so widespread, the optimizer knows it will have to scan a large number of rows to find a single case where the condition is not met. This is why it opts for a Scan. This behavior is evidenced by the estimated number of rows to be read (160’010, which represents the entire table).

On the other hand, for a very restrictive condition (quantity > 98), the optimizer recognizes that this condition is highly selective. This is why it favors a Nested Loop, estimating that only 1’608 rows will be necessary to prove the non-existence of the condition.

In summary, EXISTS forces the optimizer to estimate the number of rows required to find a single occurrence that proves whether a condition is met or not, thereby triggering a local optimization of the execution plan.

OPTION(FAST N): Manually steering the engine

The OPTION(FAST N) hint allows you to manually introduce the Row Goal concept into a query. This hint does not limit the total number of results returned; instead, it optimizes the execution plan to retrieve the first N rows as quickly as possible (potentially at the expense of performance for the remaining rows).

In our example below, we have two identical queries retrieving items with a quantity greater than 10. However, the second one uses an execution plan optimized to return the first row as fast as possible (just to make sure no one steals the last available pierogi from the top of the pile!).

select * from Inventory i
where i.Quantity > 10 
order by i.ArticleID

select * from Inventory i
where i.Quantity > 10 
order by i.ArticleID option(fast 1)

Once again, the plans diverge. To retrieve a single row, the IDX_INV_ART index (which already contains sorted ArticleIDs) is used. It performs a Seek on the smallest ArticleID to check if it satisfies the condition of having a quantity greater than 10.

However, by enabling SET STATISTICS TIME ON, we can see that the second execution plan is slower than the first when returning all requested rows (250ms vs. 204ms). While the gap is not massive due to the small table size, the difference is nonetheless observable.

Wrapping up and how to survive the Row Goal gamble

To conclude, the Row Goal is a double-edged sword; brilliant when you only need a quick glimpse of your data, but it can become a real performance trap if the optimizer’s “bet” fails.

Fortunately, if you find that SQL Server is making bad decisions by being too optimistic, you can take back control. By using the hint OPTION (USE HINT ('DISABLE_OPTIMIZER_ROWGOAL')), you force the optimizer to stop daydreaming and focus on the actual cost of the query. It’s the ultimate tool to ensure your execution plan doesn’t end up as messy as a dropped plate of pierogis!

L’article How Row Goal shapes your SQL Server query strategy by hunting for pierogis est apparu en premier sur dbi Blog.

Pages

Subscribe to Oracle FAQ aggregator