<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DBA in the shadow]]></title><description><![CDATA[Tutorials, scripts, and so on. Join me on my journey to optimize and learn.]]></description><link>https://dbaintheshadow.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 03:31:20 GMT</lastBuildDate><atom:link href="https://dbaintheshadow.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[[26ai] Hybrid Read-Only Mode PDB]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, let's talk about a new Hybrid Read-Only open-mode in 26ai.
When we set up this mode, our PDB is read-only mode for local users and read-write f]]></description><link>https://dbaintheshadow.com/26ai-hybrid-read-only-mode-pdb</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-hybrid-read-only-mode-pdb</guid><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[pdb]]></category><category><![CDATA[commonuser]]></category><category><![CDATA[localuser]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Thu, 09 Apr 2026 23:13:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/23e8f92e-f89b-4746-930e-98156e3a1ec4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-hybrid-read-only-mode-pdb"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, let's talk about a new <em><strong>Hybrid Read-Only</strong></em> open-mode in 26ai.</p>
<p>When we set up this mode, our PDB is <strong>read-only</strong> mode for <em><strong>local users</strong></em> and <strong>read-write</strong> for <strong>common users</strong>.</p>
<p>So, let's get down to business!</p>
<p>First of all, let's create a new PDB:</p>
<pre><code class="language-sql">SQL&gt; CREATE PLUGGABLE DATABASE PDB_HYBRID ADMIN USER admin IDENTIFIED BY admin keystore identified by external store;

Pluggable database created.

SQL&gt; ALTER PLUGGABLE DATABASE  PDB_HYBRID OPEN;
Pluggable database altered.

SQL&gt; ALTER PLUGGABLE DATABASE  PDB_HYBRID SAVE STATE;
Pluggable database altered.
</code></pre>
<p>Let's create both users:</p>
<pre><code class="language-sql">SQL&gt; CREATE USER c##hybrid IDENTIFIED BY "XXXXXXX";
User created.
SQL&gt; GRANT DBA TO c##hybrid CONTAINER=ALL;
Grant succeeded.

SQL&gt; alter session set container=pdb_hybrid;
SQL&gt; create smallfile tablespace tb1 
      datafile size 1m autoextend on maxsize 10m;

Tablespace created.

SQL&gt; CREATE USER hybrid IDENTIFIED BY "XXXXXXX"
  DEFAULT TABLESPACE tb1
  TEMPORARY TABLESPACE temp
  QUOTA UNLIMITED ON tb1;  

User created.

SQL&gt; GRANT DBA TO hybrid;

Grant succeeded.
</code></pre>
<p>All right, we have just created both users, on one hand, the <strong>common user</strong> is <em><strong>c##hybrid</strong></em>. On the other hand, the <strong>local user</strong> is <em><strong>hybrid</strong></em> .</p>
<p>Before opening it with the new state, let's connect as <strong>local user</strong> in order to create a table with some information:</p>
<pre><code class="language-sql">SQL&gt; conn hybrid/"XXXXX"@X.X.X.X:1521/pdb_hybrid.XXXX.XXXX.XXXX.com
Connected.
SQL&gt;      
SQL&gt; 
 Create table T_TEST AS 
  SELECT OBJECT_NAME FROM ALL_OBJECTS;

Table created.
</code></pre>
<p>Let's connect to <strong>CDB$Root</strong> in order to open the PDB in <strong>hybrid read-only</strong> mode.</p>
<pre><code class="language-sql">SQL&gt; alter pluggable database PDB_HYBRID close;

Pluggable database altered.

SQL&gt; alter pluggable database PDB_HYBRID open hybrid read only;

Pluggable database altered.

SQL&gt; r
    select con_name,
           open_mode,
           is_hybrid_read_only
    from   v$container_topology

CON_NAME             OPEN_MODE  IS_HYBRID_READ_ONLY
-------------------- ---------- --------------------
CDB$ROOT             READ WRITE NO
PDB$SEED             READ ONLY  NO
PDB_HYBRID           READ WRITE YES
</code></pre>
<p>Let's connect as <strong>local user</strong> in order to execute <em>DML</em> (delete) and <em>DDL</em> (truncate).</p>
<pre><code class="language-sql">SQL&gt;  conn hybrid/"XXXXX"@X.X.X.X:1521/pdb_hybrid.XXXX.XXXX.XXXX.com
Connected.
SQL&gt; set linesize 1000
SQL&gt; col name format a20
SQL&gt; select name, open_mode from v$pdbs;

NAME                 OPEN_MODE
-------------------- ----------
PDB_HYBRID           READ ONLY

SQL&gt; delete T_TEST;
delete T_TEST
       *
ERROR at line 1:
ORA-16000: Attempting to modify database or pluggable database that is open for read-only access.
Help: https://docs.oracle.com/error-help/db/ora-16000/


SQL&gt; truncate table T_TEST;
truncate table T_TEST
*
ERROR at line 1:
ORA-16000: Attempting to modify database or pluggable database that is open for read-only access.
Help: https://docs.oracle.com/error-help/db/ora-16000/
</code></pre>
<p>Both operations failed with the following message "<em>ORA-16000: Attempting to modify database or pluggable database that is open for read-only access</em>"</p>
<p>Let's connect as the common user in order to performn the same operations.</p>
<pre><code class="language-sql">SQL&gt;  conn c##hybrid/"FJA_2026_Oracle19c" 
Connected.

SQL&gt;  alter session set container=PDB_HYBRID;
Session altered.

SQL&gt;  select name, open_mode from v$pdbs;

NAME                 OPEN_MODE
-------------------- ----------
PDB_HYBRID           READ WRITE

SQL&gt; delete hybrid.T_TEST;

52165 rows deleted.

SQL&gt; truncate table hybrid.T_TEST;

Table truncated.
</code></pre>
<p>Both operations completed sucessfully.</p>
<p>Before calling it a day, when we check <strong>v$pdbs</strong> as local user, the value in OPEN_MODE is READ ONLY, whereas, the value for common user is READ WRITE.</p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] ALERT_LOG_MAX_SIZE]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, let's talk about a new parameter in 26ai in order to handle the size our alert log in a straightforward and efficient way. It's alert_log_max_s]]></description><link>https://dbaintheshadow.com/26ai-alert-log-max-size</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-alert-log-max-size</guid><category><![CDATA[Oracle]]></category><category><![CDATA[Oracle 26ai]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Fri, 03 Apr 2026 14:53:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/dad5c53e-425c-4e82-9bbb-e0ccec6e9a4e.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-alert-log-max-size"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, let's talk about a new parameter in 26ai in order to handle the size our alert log in a straightforward and efficient way. It's <strong>alert_log_max_size</strong> parameter.</p>
<p>The default value is 1000Mb:</p>
<pre><code class="language-sql">SQL&gt;
SQL&gt; show parameter alert_log_max_size

NAME               TYPE        VALUE
------------------ ----------- -------
alert_log_max_size big integer 1000M

SQL&gt;
</code></pre>
<p>How does Oracle handle it? Oracle splits the <strong>alert log</strong> in segments of 50Mb. In other words, we'll have 20 files of 50Mb each.</p>
<p>The parameter can only be modified at the CDB$Root, not at the PDB:</p>
<pre><code class="language-sql">SQL&gt; ALTER SYSTEM SET ALERT_LOG_MAX_SIZE = 150M; 

ALTER SYSTEM SET ALERT_LOG_MAX_SIZE = 150M 
* 
ERROR at line 1: ORA-65040: Operation is not allowed from within a pluggable database.
</code></pre>
<p>Let's write some information into the <strong>alert log</strong> in order to see how Oracle works:</p>
<pre><code class="language-sql">[oracle@~]cat save_inf.sql
begin 
declare 
 i number := 0; 
 begin 
  loop i := i + 1; 
  sys.dbms_system.ksdwrt(2, 'string(''L'',?)= ' || dbms_random.string('L',trunc(dbms_random.value(10,21)))); 
 exit when i &gt;= 10000000; 
end loop; 
end; 
end; 
/
[oracle@~] 
 watch -n 10 "sqlplus -s / as sysdba @save_inf.sql"
[oracle@l23ai alert]$ ls -lash *xml 
51M -rw-r----- 1 oracle asmdba 51M Apr 2 18:11 log_1.xml 
51M -rw-r----- 1 oracle asmdba 51M Apr 2 18:11 log_2.xml 
46M -rw-r----- 1 oracle asmdba 46M Apr 2 18:11 log.xml
</code></pre>
<p>As we can see, our <strong>alert log</strong> has been split in files of 50Mb each!.</p>
<p>A quick note about the new parameter, if we set it to zero value, then, the <strong>alert log</strong> can grown indefinitely.</p>
<p>But, can we modify the value of 50Mb? Of course. There is a hidden parameter, it's "<strong>_alert_segment_size</strong>" that allows us to change that value.</p>
<pre><code class="language-sql">SQL&gt; ALTER SYSTEM SET "_alert_segment_size" = 30;
System altered.

SQL&gt; show parameter "_alert_segment_size"

NAME               TYPE        VALUE
------------------ ----------- -------
_alert_segment_size integer     30

[oracle@l23ai ~]$ 
 watch -n 10 "sqlplus -s / as sysdba @save_inf.sql"
[oracle@l23ai alert]$ ls -lash *xml 
51M -rw-r----- 1 oracle asmdba 51M Apr 2 18:11 log_1.xml 
51M -rw-r----- 1 oracle asmdba 51M Apr 2 18:11 log_2.xml 
46M -rw-r----- 1 oracle asmdba 46M Apr 2 22:10 log_3.xml 
31M -rw-r----- 1 oracle asmdba 31M Apr 3 09:11 log_4.xml 
31M -rw-r----- 1 oracle asmdba 31M Apr 3 09:11 log_5.xml 
4.9M -rw-r----- 1 oracle asmdba 4.9M Apr 3 09:11 log.xml
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] ConnStr Tool]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, let's talk about the new feature in 26ai: the ConnStr tool.
The tool is a command-line utility that it works in order to display the connection]]></description><link>https://dbaintheshadow.com/26ai-connstr-tool</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-connstr-tool</guid><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[listener]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Wed, 25 Mar 2026 18:38:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/8316641c-ac22-45c3-a59d-4a8a7dfd9de5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-connstr-tool"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, let's talk about the new feature in 26ai: the <strong>ConnStr</strong> tool.</p>
<p>The tool is a command-line utility that it works in order to display the connections for every service in <strong>Easy Connect</strong>, <strong>JDBC</strong> and <strong>Python</strong> formats, with the option to include this information in <strong>tnsnames</strong>.</p>
<p>Another point, when we use the new tool, the listener should be up, otherwise, it will fail.</p>
<p>So, let's get down to business!</p>
<p>Let's check the <strong>listener</strong>:</p>
<pre><code class="language-sql">[oracle@~]$ lsnrctl status
LSNRCTL for Linux: Version 23.26.0.0.0 - for Oracle Cloud and Engineered Systems on 25-MAR-2026 14:28:21

Alias LISTENER 
Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production 
Start Date 09-MAR-2026 17:13:58 
Uptime 15 days 21 hr. 14 min. 23 sec 
Trace Level off 
Security ON: Local OS Authentication 
SNMP OFF 
Listener Parameter File /u01/app/23.0.0.0/grid/network/admin/listener.ora
Listener Log File /u01/app/grid/diag/tnslsnr/l23ai/listener/alert/log.xml
Listening Endpoints Summary... 
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) 
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=X.X.X.X)(PORT=1521)))

Services Summary... 
 Service "+APX" has 1 instance(s). 
Instance "+APX1", status READY, has 1 handler(s) for this service...
 Service "+ASM" has 1 instance(s). 
Instance "+ASM1", status READY, has 1 handler(s) for this service...
 Service "+ASM_DATA" has 1 instance(s). 
Instance "+ASM1", status READY, has 1 handler(s) for this service...
 Service "+ASM_RECO" has 1 instance(s). 
Instance "+ASM1", status READY, has 1 handler(s) for this service...
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s).
Instance "DB23ai", status READY, has 2 handler(s) for this service...
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service...  
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 1 handler(s) for this service...  
 Service "XXXXX.paas.oracle.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.paas.oracle.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.paas.oracle.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
 Service "XXXXX.XXXXX.XXXXX.oraclevcn.com" has 1 instance(s). 
Instance "DB23ai", status READY, has 2 handler(s) for this service... 
The command completed successfully
</code></pre>
<p>All right, the <strong>listener</strong> is up.</p>
<p>Let's execute the new command <strong>ConnStr</strong> in order to see what information we can get:</p>
<pre><code class="language-sql">[oracle@ ~]$ connstr 
Using Listener: LISTENER with Oracle Home: /u01/app/oracle/product/23.0.0.0/dbhome_1

Service Name: XXXXXXXXX.paas.oracle.com 
Connection String: X.X.X.X:1521/XXXXXXXXX.paas.oracle.com

Service Name: XXXXXXX.XXXXXX.vcn23ai.oraclevcn.com 
Connection String: X.X.X.X:1521/XXXXXX.XXXXXXXX.vcn23ai.oraclevcn.com

...
...

Connection strings can be used to connect to the specified service name.

For SQL*Plus you can use: 
SQL&gt; connect username@X.X.X.X:1521/XXXXX.paas.oracle.com

For Python you can use: 
connection = oracledb.connect(user="username", password="password", dsn="X.X.X.X:1521/XXXXXX.paas.oracle.com")

For JDBC Thin you can use: OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:@X.X.X.X:1521/XXXXXX.paas.oracle.com");
ods.setUser("username"); ods.setPassword("password");
Connection conn = ods.getConnection();

Write connect strings to tnsnames.ora (Y/N)? (Default: N):
</code></pre>
<p>Awesome! <strong>connstr</strong> displays the connection strings for <strong>Easy Connect</strong>, <strong>JDBC,</strong> and <strong>Python.</strong></p>
<p>In the last line, <strong>connstr</strong> give us the possibility to include the connection string in the <strong>tnsnames.ora</strong>!</p>
<p>In this case, we used the command directly because we have an single <strong>listenner</strong>. In case we have several listeners, we can use the following parameter in order to filter by listener "<strong>connstr -L</strong> &lt;name_listenner&gt;".</p>
<p>Other useful utitlities are as follows:</p>
<ul>
<li>List the available <strong>listeners</strong>:</li>
</ul>
<pre><code class="language-sql">[oracle@~]$ connstr -e 
PROTOCOL PORT HOST 
tcp      1521 X.X.X.X
</code></pre>
<ul>
<li>List the available services:</li>
</ul>
<pre><code class="language-sql">[oracle@~]$ connstr -s 
XXXXXXXX.paas.oracle.com 
XXXXXXXX.paas.oracle.com 
XXXXXXXX.XXXXXXXX.vcn23ai.oraclevcn.com 
pdb_david.XXXXXXXX.vcn23ai.oraclevcn.com 
+APX 
+ASM 
+ASM_DATA 
+ASM_RECO 
XXXXXXXX.XXXXXXXX.vcn23ai.oraclevcn.com 
XXXXXXXX.paas.oracle.com 
XXXXXXXX.XXXXXXXX.vcn23ai.oraclevcn.com 
XXXXXXXX.XXXXXXXX.vcn23ai.oraclevcn.com
</code></pre>
<ul>
<li>Getting the connection string in <strong>JDBC</strong> format filtered by service.</li>
</ul>
<pre><code class="language-sql">[oracle@ ~]$ connstr -j pdb_david jdbc:oracle:thin:@X.X.X.X:1521/XXXXXXXX.paas.oracle.com
</code></pre>
<ul>
<li>Getting the connection string filtered by service.</li>
</ul>
<pre><code class="language-sql">[oracle@~]$ connstr -d pdb_david
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=X.X.X.X)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XXXXXXXX.paas.oracle.com)))
</code></pre>
<ul>
<li>Getting the connection string in <strong>Easy Connect</strong> format filtered by service.</li>
</ul>
<pre><code class="language-sql">[oracle@~]$ connstr -z pdb_david 
 X.X.X.X:1521/XXXXXXXX.paas.oracle.com
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] Install Oracle AI Database 26ai on Linux 9]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we're going to see how to set up Oracle 26ai on Linux 9.
[root@~]# grep PRETTY /etc/os-release
PRETTY_NAME="Oracle Linux Server 9.7"

First of ]]></description><link>https://dbaintheshadow.com/26ai-install-oracle-ai-database-26ai-on-linux-9</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-install-oracle-ai-database-26ai-on-linux-9</guid><category><![CDATA[Linux]]></category><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[setup]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Sat, 14 Mar 2026 16:55:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/243000b4-ccef-4cab-97db-f9b47328159f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-instalaci-n-de-oracle26ai-en-linux-9"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, we're going to see how to set up Oracle 26ai on Linux 9.</p>
<pre><code class="language-shell">[root@~]# grep PRETTY /etc/os-release
PRETTY_NAME="Oracle Linux Server 9.7"
</code></pre>
<p>First of all, we need to download an Oracle 26ai pre-installation from <a href="https://yum.oracle.com/repo/OracleLinux/OL9/appstream/x86_64/getPackage/oracle-ai-database-preinstall-26ai-1.0-1.el9.x86_64.rpm">here</a>.</p>
<p>After downloading the rpm, let's set it up.</p>
<pre><code class="language-shell">root@~]# ls -lac oracle-ai-database-preinstall-26ai-1.0-1.el9.x86_64.rpm
-rw-r--r--. 1 root root 35302 mar  8 11:39 oracle-ai-database-preinstall-26ai-1.0-1.el9.x86_64.rpm
[root@~]# dnf -y install oracle-ai-database-preinstall-26ai-1.0-1.el9.x86_64.rpm
   
...
...
¡Listo!
</code></pre>
<p>Done!, Let's check whether the oracle user exists on our machine in order to create <em>ORACLE_HOME</em> directory.</p>
<pre><code class="language-shell">[root@~]# id oracle
uid=54321(oracle) gid=54321(oinstall) grupos=54321(oinstall),54322(dba),54323(oper),54324(backupdba),54325(dgdba),54326(kmdba),54330(racdba)
[root@~]# 
[root@~]# mkdir -p /u01/app/oracle/product/23.26.1/dbhome_1
[root@~]# chown -R oracle:oinstall /u01 &amp;&amp; chown -R oracle:oinstall /u01
[root@~]# su - oracle
[oracle@~]$ cd /u01/app/oracle/product/23.26.1/dbhome_1/
</code></pre>
<p>Let's edit the .bashrc and bash_profile files in order to set up the following variables:</p>
<pre><code class="language-shell">[oracle@~]$ tail -8 .bashrc
# User specific aliases and functions
ORACLE_BASE=/u01/app/oracle/
ORACLE_HOME=/u01/app/oracle/product/23.26.1/dbhome_1; export ORACLE_HOME
PATH=\(PATH:\){ORACLE_HOME}/bin; export PATH
LD_LIBRARY_PATH={ORACLE_HOME}/lib; export LD_LIBRARY_PATH
</code></pre>
<p>Lastly, let's download <strong>Oracle AI Database 26ai (23.26.1) for Linux x86-64</strong> from <a href="https://www.oracle.com/database/technologies/oracle26ai-linux-downloads.html">here</a>.</p>
<p>After downloading it, let's copy the file to the following path:</p>
<ul>
<li>/u01/app/oracle/product/23.26.1/dbhome_1.</li>
</ul>
<pre><code class="language-shell">[oracle@]$ pwd &amp;&amp; ls -lash
/u01/app/oracle/product/23.26.1/dbhome_1
total 2,3G
   0 drwxr-xr-x. 2 oracle oinstall   43 mar 14 12:12 .
   0 drwxr-xr-x. 3 oracle oinstall   22 mar  9 22:54 ..
2,3G -rwxr-x---. 1 oracle oinstall 2,3G mar 14 12:18 LINUX.X64_2326100_db_home.zip
[oracle@]$ unzip LINUX.X64_2326100_db_home.zip
</code></pre>
<p>Let's modify the response file because we'll use silent mode in order to set it up.</p>
<pre><code class="language-shell">[oracle@]$ vi install/response/db_install.rsp
[oracle@]\( grep -v "#" install/response/db_install.rsp | grep -v '^\)'
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v23.0.0
installOption=INSTALL_DB_SWONLY
UNIX_GROUP_NAME=oinstall
INVENTORY_LOCATION=${ORA_INVENTORY}
ORACLE_HOME=/u01/app/oracle/product/23.26.1/dbhome_1
ORACLE_BASE=/u01/app/oracle/
installEdition=EE
OSDBA=dba
OSBACKUPDBA=dba
OSDGDBA=dba
OSKMDBA=dba
OSRACDBA=dba
[oracle@]$ ./runInstaller -silent -responsefile install/response/db_install.rsp
</code></pre>
<p>Let's run the folowing scripts as the root user:</p>
<pre><code class="language-shell">[root@~]# .  /u01/app/oraInventory/orainstRoot.sh
...
[root@~]# .  /u01/app/oracle/product/23.26.1/dbhome_1/root.sh
...
</code></pre>
<p>Let's verify our instalation.</p>
<pre><code class="language-shell">[oracle@~]$ sqlplus /nolog

SQL*Plus: Release 23.26.1.0.0 - Production on Sat Mar 14 17:49:10 2026
Version 23.26.1.0.0

Copyright (c) 1982, 2025, Oracle.  All rights reserved.

SQL&gt; 
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[OCI] Mount a Bucket as a FS]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we are going to talk about how to mount an OCI Bucket as a FS into DB System in OCI. This can be very useful for our daily tasks.
Our DB System]]></description><link>https://dbaintheshadow.com/oci-montaje-de-un-bucket-como-un-fs</link><guid isPermaLink="true">https://dbaintheshadow.com/oci-montaje-de-un-bucket-como-un-fs</guid><category><![CDATA[OCI]]></category><category><![CDATA[bucket]]></category><category><![CDATA[Oracle Linux]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Mon, 09 Mar 2026 18:52:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/4dc1fa32-8048-442d-a214-b279e7730939.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/oci-montaje-de-un-bucket-como-un-fs"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, we are going to talk about how to mount an OCI <em>Bucket</em> as a FS into DB System in OCI. This can be very useful for our daily tasks.</p>
<p>Our DB System is running Oracle Linux Server 8.</p>
<pre><code class="language-shell">[root@~]$ grep ORACLE_* /etc/os-release
ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8"
ORACLE_BUGZILLA_PRODUCT_VERSION=8.8
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
ORACLE_SUPPORT_PRODUCT_VERSION=8.8
</code></pre>
<p>For Oracle Linux 8 onwards, we use <strong>OCIFS</strong>.</p>
<p>So, before kicking off, we should make sure that we have the following points:</p>
<ul>
<li><p>We have a <em>Bucket</em> in our <strong>tenancy</strong>.</p>
</li>
<li><p>We need to have enough space in disk in order to be used as the cache for the <strong>OCIFS</strong> utility.</p>
</li>
<li><p>By default, <strong>OCIFS</strong> uses <strong>API key-based authentication</strong> in order to autenticate. For this reason, we need to set up the OCI Cli on our machine. Below, you can see how to do it.</p>
</li>
</ul>
<p><a href="https://dbaenlasombra.com/oci-oci-cli-y-su-configuracion"><strong>[OCI] OCI-cli y su configuración</strong></a></p>
<p>Let's set up <strong>OCIFS</strong> as <strong>root</strong> user on our machine:</p>
<pre><code class="language-shell">[root@~]$ dnf install ocifs -y
...
Last metadata expiration check: 2:19:05 ago on Sun 08 Mar 2026 12:38:39 PM UTC.
Dependencies resolved.
...
Installed:
  fuse-2.9.7-19.0.1.el8.x86_64                               
  fuse-common-3.3.0-19.0.1.el8.x86_64                               
  ocifs-1.2.0-6.el8.x86_64                              
...
...
Complete!
</code></pre>
<p>Great! Next, let's check the disk space in order to know where we can create a folder. This folder will be used as the OCIFS cache.</p>
<pre><code class="language-shell">[root@~]$ 
df -h --output=source,size,used,avail,pcent,target | (read -r h; echo "$h"; sort -k2,2hr) | head -4
Filesystem                      Size  Used Avail Use% Mounted on
/dev/sdg                        196G   26G  161G  14% /u01
/dev/mapper/vg00-opt             33G  6.0G   26G  19% /opt
devtmpfs                         16G     0   16G   0% /dev
</code></pre>
<p>As we can see, /u01 has enough space.</p>
<pre><code class="language-shell">[root@~]$ mkdir /u01/tmp
</code></pre>
<p>Let's check the name of the <em>Bucket</em> that we're going to mount as a FS on our machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/bbd7ba6a-1a40-4a50-b206-f6d5363712b2.png" alt="" style="display:block;margin:0 auto" />

<p>After that, we use the <strong>ocifs</strong> command in order to mount it:</p>
<pre><code class="language-shell">[root@~]$ mkdir /mybucket 
[root@~]$ ocifs --cache=/u01/tmp &lt;name_bucket&gt; /mybucket
[root@~]$ df -h /mybucket
Filesystem            Size  Used Avail Use% Mounted on
&lt;name_bucket&gt;          0     0     0    - /mybucket
[root@l23ai ~]# grep mybucket /proc/mounts
&lt;name_bucket&gt; /mybucket fuse.ocifs rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions 0 0
</code></pre>
<p>Now, we can see our <em>Bucket</em> as a FS. Moreover, we can see a new line in <strong>/proc/mounts</strong> file.</p>
<p>Lastly, let's create a file with some sample content:</p>
<pre><code class="language-shell">[root@~]$ 
 touch /mybucket/passwd.bck &amp;&amp; cat /etc/passwd &gt; /mybucket/passwd.bck
</code></pre>
<p>Below, you can see that the file is correctly stored in our <em>Bucket</em> :</p>
<img src="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/6e98eae6-a65b-4f8b-bd2e-d9cd6649a313.png" alt="" style="display:block;margin:0 auto" />

<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] DBMS_CLOUD — Chapter Two]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Cointinuing with the last article, where we looked at how to set up DBMS_CLOUD in our database and took the firsts steps., today, we're going to see h]]></description><link>https://dbaintheshadow.com/26ai-dbms-cloud-chapter-two</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-dbms-cloud-chapter-two</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[bucket]]></category><category><![CDATA[datapump]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Tue, 24 Feb 2026 16:25:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/dafc38ec-0438-45d3-8f94-bb7640ba58a4.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-dbms-cloud-capitulo-dos"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Cointinuing with the last article, where we looked at how to set up <em>DBMS_CLOUD</em> in our database and took the firsts steps., today, we're going to see how to use <em>DBMS_CLOUD</em> with Oracle Datapump.</p>
<p>Below, you can see the first chapter:</p>
<p><a href="https://dbaenlasombra.com/26ai-dbms-cloud-capitulo-uno">[26ai] DBMS_CLOUD — Capitulo Uno</a></p>
<p>Our lab will have two sections, as follows:</p>
<ul>
<li><p>Export a table to a <em>Bucket.</em></p>
</li>
<li><p>Import into the table the information from the previous step.</p>
</li>
</ul>
<h3><strong>Export to a <em>Bucket</em></strong></h3>
<p>Let's create a table. We'll use this table in order to perform the export :</p>
<pre><code class="language-sql">SQL&gt; 
  Create Table My_Grants As  
   Select TABLE_SCHEMA,TABLE_NAME,PRIVILEGE  
     From All_Tab_Privs;

 Table created.

SQL&gt; set linesize 1000 pages 1000
SQL&gt; col TABLE_SCHEMA format a20
SQL&gt; col table_name format a20
SQL&gt; col privilege format a20
SQL&gt; r
  1* Select * From My_Grants FETCH FIRST 10  ROWS ONLY

TABLE_SCHEMA         TABLE_NAME                     PRIVILEGE
-------------------- ------------------------------ --------------------
SYS                  DUAL                           SELECT
SYS                  SYSTEM_PRIVILEGE_MAP           READ
SYS                  TABLE_PRIVILEGE_MAP            READ
SYS                  USER_PRIVILEGE_MAP             READ
SYS                  STMT_AUDIT_OPTION_MAP          READ
SYS                  FINALHIST$                     INSERT
SYS                  DM$EXPIMP_ID_SEQ               SELECT
SYS                  MODELGTTRAW$                   SELECT
SYS                  MODELGTTRAW$                   INSERT
SYS                  PMAPGTT$                       SELECT
</code></pre>
<p>Moreover, we're going to use the <strong>DEFAULT_CREDENTIAL</strong> property in order to set our credential as the default.</p>
<pre><code class="language-sql">SQL&gt; 
ALTER DATABASE PROPERTY SET DEFAULT_CREDENTIAL = 'TEST.DBA_IN_THE_SHADOW';

Database altered.

SQL&gt; 
Select PROPERTY_NAME,PROPERTY_VALUE 
  From database_properties  
 Where PROPERTY_NAME= 'DEFAULT_CREDENTIAL';

PROPERTY_NAME        PROPERTY_VALUE                           
-------------------- ---------------------------------------- 
DEFAULT_CREDENTIAL   TEST.DBA_IN_THE_SHADOW                    
</code></pre>
<p>Let's create a parfile in order to perform the export:</p>
<pre><code class="language-sql">SQL&gt; ! vi export_to_bucket.par
SQL&gt; ! cat export_to_bucket.par
DUMPFILE=&lt;location_uri&gt;/&lt;TABLE&gt;.dmp
LOGFILE=&lt;TABLE&gt;.log
TABLES=&lt;SCHEMA&gt;.&lt;TABLE&gt;
CONTENT=DATA_ONLY
LOGTIME=ALL
METRICS=YES
FLASHBACK_TIME=SYSTIMESTAMP
ENCRYPTION_PASSWORD=hari
</code></pre>
<p>Our parfile is as follows:</p>
<ul>
<li><p>DUMPILE: <em>Bucket</em> URL in order to save the export.</p>
</li>
<li><p>LOGFILE: Log name.</p>
</li>
<li><p>TABLES: Here, we fill in the parameter with the name of the table that we created in the previous step.</p>
</li>
<li><p>CONTENT=DATA_ONLY: Export Data only.</p>
</li>
<li><p>LOGTIME/METRICS: Time Metrics .</p>
</li>
<li><p>FLASHBACK_TIME: Consistent data export.</p>
</li>
<li><p>ENCRYPTION_PASSWORD: Encrypt our <strong>dmp</strong> file.</p>
</li>
</ul>
<p>Let's execute the <em>export</em>:</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/65605419d28f19cc44df7ef1/abcbe616-5049-4a34-b90e-db8f57914a8c.png" alt="" style="display:block;margin:0 auto" />

<p>Let's check our <strong>dmp</strong> in our<em>Bucket</em>:</p>
<pre><code class="language-sql">SQL&gt; 
Select object_name, trunc(bytes / (1024*1024),2) MB
  From 
   dbms_cloud.list_objects('DBA_IN_THE_SHADOW', '&lt;location_uri&gt;'); 

OBJECT_NAME                                      MB
---------------------------------------- ----------
ORA7445pf_20260205085710_COM_1.zip            57.35
Wallet_OF2BAP.zip                               .02
Wallet_OF2BCE.zip                               .02
grant.dmp                                         0
grant.dmp_segments/aaaaaa                         2
grant.dmp_segments/aaaaab                       .86

6 rows selected.
</code></pre>
<p>Regarding our <strong>dmp</strong> inside out <em>Bucket</em>, we can see three files even though we haven't used any wildcards, such as <strong>%L</strong>, <strong>%l</strong>, <strong>%U,</strong> or <strong>%u</strong>. Moreover, the size of our <strong>dmp</strong> is zero, while the DMP fragments have weigth. How come? Because Data Pump splits the dmp into smaller pieces in order to improve load performance.</p>
<h3><strong>ImportIng from a <em>Bucket</em></strong></h3>
<p>Before executing the import , we need to create a table in order to store the data:</p>
<pre><code class="language-sql">SQL&gt; CREATE TABLE MY_GRANTS_BCK AS SELECT * FROM MY_GRANTS WHERE 2 = 1;

Table created.
SQL&gt; ! vi import_to_bucket.par
SQL&gt; ! cat import_to_bucket.par
DUMPFILE=&lt;location_uri&gt;/&lt;TABLE&gt;.dmp
LOGFILE=MY_GRANTS.log
LOGTIME=ALL
METRICS=YES
REMAP_TABLE = TEST.MY_GRANTS:MY_GRANTS_BCK
encryption_password=yes
</code></pre>
<p>Our parfile is as follows:</p>
<ul>
<li><p>DUMPILE: <em>Bucket</em> URL in order to get the export.</p>
</li>
<li><p>LOGFILE: Log name.</p>
</li>
<li><p>LOGTIME/METRICS: Time Metrics.</p>
</li>
<li><p>REMAP_TABLE: We want to store the information in another table, so we need to use the REMAP_TABLE parameter.</p>
</li>
<li><p>ENCRYPTION_PASSWORD= Our <strong>dmp</strong> is encrypted.</p>
</li>
</ul>
<p>Let's execute the <em>import</em>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/1f70eaba-7bce-42eb-befe-5fcb06d93874.png" alt="" style="display:block;margin:0 auto" />

<p>Perfect, we have been able to use our <em>Bucket</em> with <strong>Oracle Data Pump</strong>.</p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] DBMS_CLOUD — Chapter One]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we're going to talk about DBMS_CLOUD on 26ai, and how we use it our daily tasks such as saviing Data Pump backups or generating reports, becaus]]></description><link>https://dbaintheshadow.com/26ai-dbms-cloud-chapter-one</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-dbms-cloud-chapter-one</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[dbms_cloud]]></category><category><![CDATA[bucket]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Fri, 20 Feb 2026 00:38:41 GMT</pubDate><enclosure url="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/65605419d28f19cc44df7ef1/809820c3-f9e6-4f5a-9eb1-c562e5502ca2.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a href="https://dbaenlasombra.com/26ai-dbms-cloud-capitulo-uno"><em><strong>Spanish version</strong></em></a><em>.</em></p>
<p>Today, we're going to talk about <em>DBMS_CLOUD</em> on 26ai, and how we use it our daily tasks such as saviing Data Pump backups or generating reports, because this package connects to OCI <em>Object Storage</em> .</p>
<p>By default, <em>DBMS_CLOUD</em> isn't set up on 26ai, we need to configure it with a valid user from our <strong>tenancy</strong>,</p>
<p>Before getting our hands dirty, we must be absolutely sure that <em>DBMS_CLOUD</em> is working our database.</p>
<p>Just in case, below, you can see the Oracle's note on how to set up in our database:</p>
<p><a href="https://support.oracle.com/support/?anchorId=&amp;kmContentId=2748362&amp;page=sptemplate&amp;sptemplate=km-article"><em><strong>How To Setup And Use DBMS_CLOUD Package (Doc ID 2748362.1)</strong></em></a></p>
<p>After that, we need to configure a <strong>token</strong> or an <strong>API Key</strong> for our OCI account**.** This step is neccessary because our <em>Bucket</em> is private. So we need to create a <strong>credential</strong>. If our <em>Bucket</em> were public, this step would not be required.</p>
<h3><strong>Token</strong></h3>
<p>First all, we're going to generate a token for our OCI account.</p>
<p>Let's go to the top right of the console and click <strong>My profile</strong>:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771410019467/915ef3cc-14f9-41d5-9e8f-feb4566a6036.png" alt="" style="display:block;margin:0 auto" />

<p>Click <strong>Tokens and keys tab</strong>:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771329298121/73011e3f-f972-434c-9386-e50f55798bf7.png" alt="" style="display:block;margin:0 auto" />

<p>Let's look at three sections: <em>API Keys</em>, <em>Auth Tokens</em> and <em>Customer Secrets Keys</em>.</p>
<p>Our option is <em>Auth Tokens</em>:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771329519186/02251fb9-d8c1-4ecb-b635-417e614f8d0a.png" alt="" style="display:block;margin:0 auto" />

<p>Here, click in <em>Generate token</em>. We just need tofill in a name and clicking <em>Generate token</em>:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771329590592/50419b9d-06d2-476b-b216-4b8fc0a8f0c0.png" alt="" style="display:block;margin:0 auto" />

<p>We musn't close the next window before copying the token vale.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771329749038/4ebb4308-6ad9-4092-a766-1e20ff09a5b9.png" alt="" style="display:block;margin:0 auto" />

<p>After completing the previous step, Let's define the credential in our database using the token we just created.</p>
<h3><strong>Creation of the Credential</strong></h3>
<p>Let's use <strong>DBMS_CLOUD.CREATE_CREDENTIAL</strong>.</p>
<p>This procedure receives the following parameters:</p>
<ul>
<li><p>CREDENTIAL_NAME: Name of the credential.</p>
</li>
<li><p>USERNAME:<em>/&lt;username_in_the_tenancy&gt;</em>.</p>
</li>
<li><p>Password: Token value that we generated in the previous step.</p>
</li>
</ul>
<pre><code class="language-sql">SQL&gt;EXEC  dbms_cloud.create_credential(
    credential_name =&gt; 'DBA_IN_THE_SHADOW',
    username        =&gt; '&lt;IdentityDomain&gt;/&lt;usuario_tenancy&gt;',
    password        =&gt; '&lt;token&gt;');

SQL&gt; R
  1  select credential_name,
  2         username,
  3         enabled
  4  from   DBA_credentials
  5* order by credential_name

CREDENTIAL_NAME           USERNAME                                           ENABLED
------------------------- -------------------------------------------------- --------------------
DBA_IN_THE_SHADOW         &lt;IdentityDomain&gt;/&lt;usuario_tenancy&gt;       TRUE
</code></pre>
<p>Let's check our credential using <strong>DBMS_CLOUD.LIST_OBJECTS</strong>. With this function, we can list the contents of the <em>Bucket</em>**.** Thus, we need to verify the connectivity with OCI.</p>
<p>This function needs several parameters, such as name of the credential and the URL in order to access our<em>Bucket</em>.</p>
<p>How do you get the url of our <em>Bucket</em>? The easiest way is to access an object in our <em>Bucket</em> and then go to the details:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771411079006/0d136145-6a8c-487d-b28a-7edff7d3abda.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1771411298002/5eee5747-6775-4097-9424-7e33298cdd84.png" alt="" style="display:block;margin:0 auto" />

<p>Here, we copy of the “<em>URL path (URI)</em>”.</p>
<p>After that, let's check the contents of our <em>Bucket</em> using SQL:</p>
<pre><code class="language-sql">SQL&gt; 
Select object_name
  From Dbms_cloud.list_objects('DBA_IN_THE_SHADOW','&lt;location_uri&gt;'); 

OBJECT_NAME
--------------------------------------------------------------------------------
XXXXXXXX.zip
XXXXXXXX.zip
XXXXXXXX.zip
</code></pre>
<p>Perfect, the access was sucessful.</p>
<h3><strong>Uploading files</strong></h3>
<p>In the next step, on one hand, we're going to create a <strong>csv</strong> file, and on the other hand we'll upload it to our <em>Bucket</em>.</p>
<p>Let's use <strong>DBMS_CLOUD.PUT_OBJECTS</strong> in order to upload it. Before using it, we need to create a directory object in Oracle.</p>
<pre><code class="language-sql">SQL&gt; ! cat generate.sql
set heading off
set feedback off
set echo off
set verify off
set termout off
set markup csv on
spool myfile.csv
Select trunc(dbms_random.value(1, 1000)), dbms_random.string('x', 10)     
 From dual  
connect by level &lt;= 10000;
spool off

SQL&gt; @generate.sql
SQL&gt; ! ls -lac *csv
-rw-r--r-- 1 oracle oinstall 168924 Feb 18 12:42 myfile.csv

SQL&gt; CREATE DIRECTORY OCI_HOME as '/home/oracle';
SQL&gt; GRANT READ, WRITE ON DIRECTORY OCI_HOME TO PUBLIC;
SQL&gt; begin
  dbms_cloud.put_object (
    credential_name =&gt; 'DBA_IN_THE_SHADOW',
    object_uri      =&gt; '&lt;location_uri&gt;/myfile.csv',
    directory_name  =&gt; 'OCI_HOME',
    file_name       =&gt; 'myfile.csv');
end;
/ 
SQL&gt;
SQL&gt; Select object_name
  From 
   dbms_cloud.list_objects('DBA_IN_THE_SHADOW','&lt;location_uri&gt;');  

OBJECT_NAME
--------------------------------------------------------------------------------
XXXXXXXX.zip
XXXXXXXX.zip
XXXXXXXX.zip
myfile.csv
</code></pre>
<p>Perfect, we have uploaded the file to our <em>Bucket</em>.</p>
<p>As the file is in our Bucket, we can create an external table in order to read the file. The easiest way is to use <strong>DBMS_CLOUD.CREATE_EXTERNAL_TABLE</strong>, because it generates a table in our schema. This table reads the file directly.</p>
<pre><code class="language-sql">SQL&gt; 
BEGIN
  DBMS_CLOUD.CREATE_EXTERNAL_TABLE(
    table_name      =&gt; 'EXT_MYFILE_CSV',
    credential_name =&gt; 'DBA_IN_THE_SHADOW',
    file_uri_list   =&gt; '&lt;location_uri&gt;/myfile.csv',
    format          =&gt; JSON_OBJECT(
                         'type' VALUE 'csv',
                         'delimiter' VALUE ',',
                         'quote' VALUE '"',
                         'skipheaders' VALUE '0'
                       ),
    column_list     =&gt; '
        id   NUMBER,
        code VARCHAR2(50)
    '
  );
END;
/

SQL&gt; SELECT COUNT(*) FROM EXT_MYFILE_CSV;
1000
SQL&gt;
 SELECT * FROM EXT_MYFILE_CSV FETCH FIRST 25 ROWS ONLY
        ID CODE
---------- --------------------------------------------------
       224 3LU82RWW27
       654 LASYRZWUUE
        17 UW34WB3O4Y
       764 5Z2I01ITAX
       132 V4XCFDS9GA
       131 6PRK6G0VTC
       650 NST09S6RY9
       133 R8IIPLJZ95
       477 WK8Y1XC5XK
       930 O574M5RJK2
       371 P8G6PF91A9
       214 WRUYMY4BWY
       273 YD5NG441MV
       706 DQYEBYNF5H
       699 J3T3RHNHU0
       744 VVXATGVW0N
       945 U55X9EATLH
       371 RHW44MZ1DQ
       595 B1RU6VN33B
       864 P02I2A9Z8S
       218 R02XSI9MLY
       980 M0CSWHE4G7
       396 UZYFEL7UKI
       619 DYKCFI912X
       881 2TZ0GEQ6MM

25 rows selected.
</code></pre>
<p>We can also export the information to our <em>Bucket</em> using <strong>DBMS_CLOUD.EXPORT_DATA</strong>.</p>
<p>This procedure has the following paramaters:</p>
<ul>
<li><p>CREDENTIAL_NAME: Name of the credential.</p>
</li>
<li><p>URL: “<em>URL path (URI)</em>”.</p>
</li>
<li><p>Format: In our case, the format is <strong>json</strong>.</p>
</li>
<li><p>Query: A valid SQL query.</p>
</li>
</ul>
<pre><code class="language-sql">SQL&gt; 
BEGIN
      DBMS_CLOUD.EXPORT_DATA(  
        credential_name =&gt;'DBA_IN_THE_SHADOW',
        file_uri_list =&gt;'&lt;location_uri&gt;/config_system_parameter',
        format =&gt; json_object(  'type' VALUE 'json' ),
        query =&gt; 'SELECT NAME, VALUE FROM V$SYSTEM_PARAMETER'
      );
   END;
  / 

SQL&gt; Select object_name
  From 
   dbms_cloud.list_objects('DBA_IN_THE_SHADOW','&lt;location_uri&gt;');  

OBJECT_NAME
--------------------------------------------------------------------------------
XXXXXXXX.zip
XXXXXXXX.zip
XXXXXXXX.zip
config_system_parameter_1_1_1.json
myfile.csv
</code></pre>
<p>And if we need to load the file into a table, we can use <strong>DBMS_CLOUD.COPY_DATA</strong>.</p>
<pre><code class="language-sql">SQL&gt; 
  Create table BACK_SYSTEM_PARAMETER ( 
    INFO_PARAMETER CLOB  CONSTRAINT INFO_PARAMETER_JSON CHECK ( INFO_PARAMETER IS JSON )
      );

Table created.

SQL&gt;
begin
  DBMS_CLOUD.COPY_DATA (
    table_name      =&gt; 'BACK_SYSTEM_PARAMETER',
    credential_name =&gt; 'DBA_IN_THE_SHADOW',
    file_uri_list   =&gt; '&lt;location_uri&gt;/config_system_parameter_1_1_1.json'
     );
end;
/
PL/SQL procedure successfully completed.
</code></pre>
<p>Before using the procedure, we're going to create <em>BACK_SYSTEM_PARAMETER table with a single column</em> in order to load the file.</p>
<p>Let's query the table in order to see the contents of the file:</p>
<pre><code class="language-sql">SQL&gt;
 select 
    JSON_VALUE(INFO_PARAMETER, '$.NAME') AS NAME, 
    JSON_VALUE(INFO_PARAMETER, '$.VALUE') AS VALUE 
   from BACK_SYSTEM_PARAMETER
 Where INSTR(UPPER(JSON_VALUE(INFO_PARAMETER, '$.NAME')),'OPTIMIZER') != 0
  FETCH FIRST 5 ROWS ONLY;

NAME                                     VALUE
---------------------------------------- ----------------------------------------
optimizer_ignore_hints                   FALSE
optimizer_secure_view_merging            TRUE
optimizer_use_pending_statistics         FALSE
optimizer_capture_sql_plan_baselines     FALSE
optimizer_use_sql_plan_baselines         TRUE

10 rows selected.
</code></pre>
<p>In the next article, we're explore how to use <em>Data Pump</em> using <em>DBMS_CLOUD</em></p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] Blockchain & Immutable table]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we’re going to talk about Blockchain tables and Immutable tables.
Both were introduced in Oracle in order to protect against unauthorized data modification by external user, you can only insert...]]></description><link>https://dbaintheshadow.com/26ai-blockchain-and-immutable-table</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-blockchain-and-immutable-table</guid><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[tables]]></category><category><![CDATA[cdbroot]]></category><category><![CDATA[pdb]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Thu, 12 Feb 2026 14:20:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770851956211/7149d75c-d6c8-479a-8086-e1dfa9cf2cf6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/26ai-blockchain-and-immutable-table"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>Today, we’re going to talk about <strong>Blockchain tables</strong> and <strong>Immutable tables</strong>.</p>
<p>Both were introduced in Oracle in order to protect against unauthorized data modification by external user, you can only <strong>insert rows</strong>. Unlike <strong>Immutable tables</strong>, <strong>Blockchain tables</strong> include a <strong>cryptographic hash</strong> for every row.</p>
<p>Even though it’s not a feature in <strong>26ai,</strong> it was available in <strong>21c</strong>. However, several new features have been introduced in the latest release such as:</p>
<ul>
<li><p>Adding and removing columns in <strong>Blockchain</strong> and <strong>Immutable tables</strong>, it’s always specifically <strong>VERSION v2</strong> of these tables. Below you can see how it works:</p>
<pre><code class="lang-sql">  SQL&gt; 
  <span class="hljs-keyword">CREATE</span> IMMUTABLE <span class="hljs-keyword">TABLE</span> T_TEST_VRS_1 (
    TC_ID <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">BY</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span> PRIMARY <span class="hljs-keyword">KEY</span>
  )
  <span class="hljs-keyword">no</span> <span class="hljs-keyword">drop</span> <span class="hljs-keyword">until</span> <span class="hljs-number">2</span> <span class="hljs-keyword">days</span> idle
  <span class="hljs-keyword">no</span> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">until</span> <span class="hljs-number">16</span> <span class="hljs-keyword">days</span> <span class="hljs-keyword">after</span> <span class="hljs-keyword">insert</span>
  <span class="hljs-keyword">VERSION</span> <span class="hljs-string">"v1"</span>;

  Table created.
  SQL&gt;  <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_TEST_VRS_1 <span class="hljs-keyword">ADD</span> (FECHA <span class="hljs-built_in">DATE</span>);
  ERROR at line 1:
  ORA-05715: operation not allowed on the blockchain or immutable table
  <span class="hljs-keyword">Help</span>: https://docs.oracle.com/<span class="hljs-keyword">error</span>-<span class="hljs-keyword">help</span>/db/ora<span class="hljs-number">-05715</span>/

  <span class="hljs-keyword">SQL</span>&gt; 
  <span class="hljs-keyword">CREATE</span> IMMUTABLE <span class="hljs-keyword">TABLE</span> T_TEST_VRS_2 (
    TC_ID <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">BY</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span> PRIMARY <span class="hljs-keyword">KEY</span>
  )
  <span class="hljs-keyword">no</span> <span class="hljs-keyword">drop</span> <span class="hljs-keyword">until</span> <span class="hljs-number">2</span> <span class="hljs-keyword">days</span> idle
  <span class="hljs-keyword">no</span> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">until</span> <span class="hljs-number">16</span> <span class="hljs-keyword">days</span> <span class="hljs-keyword">after</span> <span class="hljs-keyword">insert</span>
  <span class="hljs-keyword">VERSION</span> <span class="hljs-string">"v2"</span>;

  SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_TEST_VRS_2 <span class="hljs-keyword">ADD</span> (FECHA <span class="hljs-built_in">DATE</span>);
  Table altered.
</code></pre>
</li>
<li><p><strong>BLOCKCHAIN_TABLE_MAX_NO_DROP</strong>, a new parameter that controls the amount of idle time the table must be inactive before it can be dropped. When the parameter has a value and a user creates a new table with <strong>NO DROP UNTIL</strong> n <strong>DAYS IDLE</strong> clause, the value of <strong>n</strong> must be less than or equal to the parameter. However, if the parameter is null, any value can be used in the clause.</p>
</li>
</ul>
<p>Rows can’t be deleted while it is within the specified retention period. The same applies to dropping the table. When the retention period expires, you can delete rows or drop the table.</p>
<h3 id="heading-retention-period"><strong>Retention Period</strong></h3>
<p>In the following diagram, we can see the different options available in order to set up our tables:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770905284440/cf2328b6-9839-4ec6-bf50-d31b632c045b.png" alt class="image--center mx-auto" /></p>
<p>Table level:</p>
<ul>
<li><p><strong>NO DROP</strong>: The table can’t be dropped unless it’s empty.</p>
</li>
<li><p><strong>NO DROP UNTIL</strong> n <strong>DAYS IDLE</strong>: If there are rows within the specified retention period, the table can’t be dropped. By default, it’s 0, although a minimal value of 16 is recommended.</p>
</li>
</ul>
<p>Row level:</p>
<ul>
<li><p><strong>NO DELETE [<em>locked</em>]</strong>: Each row is retained forever. La clausula <strong>[<em>locked</em>]</strong> especifica que no se puede modificar la retención.</p>
</li>
<li><p><strong>NO DELETE UNTIL</strong> n <strong>DAYS AFTER INSERT [<em>locked</em>]</strong>: Cada fila no puede ser eliminada, es decir, esta protegida de la eliminación tantos días como especifiquemos en la cláusula n <strong>DAYS</strong>. Valor mínimo es 16 días. La clausula <strong>[<em>locked</em>]</strong> especifica que no se puede modificar la retención.</p>
</li>
</ul>
<h3 id="heading-restrictions"><strong>Restrictions</strong></h3>
<p>Be aware of the following points:</p>
<ul>
<li><p>The following data types are not supported: <em>ROWID</em>, <em>UROWID, LONG, OBJECT TYPE, REF, VARRAY, NESTED TABLE, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE, BFILE</em> y <em>XMLType.</em></p>
</li>
<li><p>It can’t be <em>INDEX-ORGANIZED, ORGANIZATION CUBE, ORGANIZATION EXTERNAL</em> o <em>HIBRYD PARTITIONED</em>.</p>
</li>
</ul>
<p>So, let's get down to business!</p>
<p><strong>Inmutable Table</strong></p>
<pre><code class="lang-sql">SQL&gt; 
<span class="hljs-keyword">CREATE</span> IMMUTABLE <span class="hljs-keyword">TABLE</span> T_CLIENTES (
  TC_ID <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">BY</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span> PRIMARY <span class="hljs-keyword">KEY</span>,
  TC_name   <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  TC_email       <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">200</span>),
  TC_created_at  <span class="hljs-built_in">DATE</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">SYSDATE</span>
)
<span class="hljs-keyword">no</span> <span class="hljs-keyword">drop</span> <span class="hljs-keyword">until</span> <span class="hljs-number">2</span> <span class="hljs-keyword">days</span> idle
<span class="hljs-keyword">no</span> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">until</span> <span class="hljs-number">16</span> <span class="hljs-keyword">days</span> <span class="hljs-keyword">after</span> <span class="hljs-keyword">insert</span>
<span class="hljs-keyword">VERSION</span> <span class="hljs-string">"v2"</span>;

Table created.
</code></pre>
<p>If we need to modify the retention period, we can do it as follows:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_CLIENTES  <span class="hljs-keyword">NO</span> <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">5</span> <span class="hljs-keyword">DAYS</span> IDLE;
Table altered.
SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_CLIENTES  <span class="hljs-keyword">NO</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">32</span> <span class="hljs-keyword">DAYS</span> <span class="hljs-keyword">AFTER</span> <span class="hljs-keyword">INSERT</span>;
Table altered.
</code></pre>
<p>Let’s add columns,as the table uses the <strong>VERSION v2</strong> clause:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_CLIENTES <span class="hljs-keyword">ADD</span> (TC_PROVINCIA <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>));
</code></pre>
<p>Let’s insert some data and try to modify it:</p>
<pre><code class="lang-sql">SQL&gt; r
  1* <span class="hljs-keyword">Select</span> * <span class="hljs-keyword">From</span> t_Clientes

     TC_ID TC_NAME              TC_EMAIL             TC_CREATE TC_PROVINCIA
<span class="hljs-comment">---------- -------------------- -------------------- --------- ----------------------------------------------------------------------------------------------------</span>
         <span class="hljs-number">1</span> Iker San             San@demo.local       <span class="hljs-number">11</span>-FEB<span class="hljs-number">-26</span>
         <span class="hljs-number">2</span> Juan Perro           Perro@demo.local     <span class="hljs-number">11</span>-FEB<span class="hljs-number">-26</span>
         <span class="hljs-number">3</span> Carla Marq           Marq@demo.local      <span class="hljs-number">11</span>-FEB<span class="hljs-number">-26</span>

<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">Update</span> t_Clientes <span class="hljs-keyword">Set</span> Tc_Provincia=<span class="hljs-string">'VALLADOLID'</span> <span class="hljs-keyword">where</span> tc_id = <span class="hljs-number">3</span>;
<span class="hljs-keyword">Update</span> t_Clientes <span class="hljs-keyword">Set</span> Tc_Provincia=<span class="hljs-string">'VALLADOLID'</span> <span class="hljs-keyword">where</span> tc_id = <span class="hljs-number">3</span>
       *
<span class="hljs-keyword">ERROR</span> <span class="hljs-keyword">at</span> line <span class="hljs-number">1</span>:
ORA<span class="hljs-number">-05715</span>: operation <span class="hljs-keyword">not</span> allowed <span class="hljs-keyword">on</span> the blockchain <span class="hljs-keyword">or</span> immutable <span class="hljs-keyword">table</span>
<span class="hljs-keyword">Help</span>: https://docs.oracle.com/<span class="hljs-keyword">error</span>-<span class="hljs-keyword">help</span>/db/ora<span class="hljs-number">-05715</span>/
</code></pre>
<p>As we can see, we can’t modify the information, we can only insert new registers.</p>
<h3 id="heading-blockchain-table"><strong>Blockchain Table</strong></h3>
<pre><code class="lang-sql">SQL&gt; 
<span class="hljs-keyword">CREATE</span> BLOCKCHAIN <span class="hljs-keyword">TABLE</span> T_PRODUCTOSTIENDA (
  TP_id       <span class="hljs-built_in">NUMBER</span>,
  TP_NOMBRE   <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>),
  TP_PRICE    <span class="hljs-built_in">FLOAT</span>
)
<span class="hljs-keyword">NO</span> <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">14</span> <span class="hljs-keyword">DAYS</span> IDLE
<span class="hljs-keyword">NO</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">30</span> <span class="hljs-keyword">DAYS</span> <span class="hljs-keyword">AFTER</span> <span class="hljs-keyword">INSERT</span>
HASHING <span class="hljs-keyword">USING</span> <span class="hljs-string">"SHA2_512"</span>
<span class="hljs-keyword">WITH</span> <span class="hljs-keyword">ROW</span> <span class="hljs-keyword">VERSION</span> <span class="hljs-keyword">AND</span> <span class="hljs-keyword">USER</span> <span class="hljs-keyword">CHAIN</span> T_PRODUCTOS_VALIDATION (TP_id)
<span class="hljs-keyword">VERSION</span> <span class="hljs-string">"v2"</span>;  

Table created.
</code></pre>
<p>If we need to modify the retention period, we can do it as follows:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_PRODUCTOSTIENDA  <span class="hljs-keyword">NO</span> <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">16</span> <span class="hljs-keyword">DAYS</span> IDLE;
Table altered.
SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_PRODUCTOSTIENDA  <span class="hljs-keyword">NO</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">UNTIL</span> <span class="hljs-number">32</span> <span class="hljs-keyword">DAYS</span> <span class="hljs-keyword">AFTER</span> <span class="hljs-keyword">INSERT</span>;
Table altered.
</code></pre>
<p>Let’s add columns,as the table uses the <strong>VERSION v2</strong> clause:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> T_PRODUCTOSTIENDA <span class="hljs-keyword">ADD</span> (TC_CANTIDAD <span class="hljs-built_in">INTEGER</span>);
</code></pre>
<p>Let’s insert some data and try to modify it:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">Select</span> * <span class="hljs-keyword">From</span> T_PRODUCTOSTIENDA;

     TP_ID TP_NOMBRE              TP_PRICE TC_CANTIDAD
<span class="hljs-comment">---------- -------------------- ---------- -----------</span>
         1 PERAS
         1 PERAS JULIANAS
         2 NARANJAS
         3 MANGOS

SQL&gt; <span class="hljs-keyword">UPDATE</span> T_PRODUCTOSTIENDA <span class="hljs-keyword">SET</span> TP_PRICE = <span class="hljs-number">9</span>;
<span class="hljs-keyword">UPDATE</span> T_PRODUCTOSTIENDA <span class="hljs-keyword">SET</span> TP_PRICE = <span class="hljs-number">9</span>
       *
<span class="hljs-keyword">ERROR</span> <span class="hljs-keyword">at</span> line <span class="hljs-number">1</span>:
ORA<span class="hljs-number">-05715</span>: operation <span class="hljs-keyword">not</span> allowed <span class="hljs-keyword">on</span> the blockchain <span class="hljs-keyword">or</span> immutable <span class="hljs-keyword">table</span>
<span class="hljs-keyword">Help</span>: https://docs.oracle.com/<span class="hljs-keyword">error</span>-<span class="hljs-keyword">help</span>/db/ora<span class="hljs-number">-05715</span>/
</code></pre>
<p>As we can see, we can’t modify the information, we can only insert new registers. If you look at the SQL output, we can see two rows with the same tp_id, but…which one was inserted last? In this type of table, Oracle automatically generates a view called <strong>&lt;TABLE_NAME&gt;_LAST$</strong> in order to display the latest version of each record.</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">Select</span> * <span class="hljs-keyword">From</span> T_PRODUCTOSTIENDA_LAST$;

     TP_ID TP_NOMBRE              TP_PRICE
<span class="hljs-comment">---------- -------------------- ----------</span>
         1 PERAS JULIANAS
         2 NARANJAS
         3 MANGOS
</code></pre>
<p>In future articles, we will cover the topic of deletion based on the examples we’ve used.</p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] Mandatory Profile]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we’re going to talk about Mandatory Profile.
Even though It’s not a feature in 26ai, it was available in 21c, we’re going to set it up in the latest release.
This type of Profile can be created...]]></description><link>https://dbaintheshadow.com/26ai-mandatory-profile</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-mandatory-profile</guid><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[cdbroot]]></category><category><![CDATA[pdb]]></category><category><![CDATA[profile]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Thu, 29 Jan 2026 14:30:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769691076448/7a11c52a-8784-4409-a20a-817aeeb70a8f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/26ai-mandatory-profile"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>Today, we’re going to talk about <strong>Mandatory Profi</strong><a target="_blank" href="https://dbaenlasombra.com/26ai-oracle-temporary-tablespace-groups"><strong>le</strong>.</a></p>
<p>Even though It’s not a feature in <strong>26ai,</strong> it was available in <strong>21c</strong>, we’re going to set it up in the latest release.</p>
<p>This type of <strong>Profile</strong> can be created at the <em>CDB$Root</em> and can be assigned to our <em>PDBs</em>. Another important point is that if we need to upgrade it, we must do it at the CDB$ROOT, <strong>not</strong> at the PDB level, and using <strong>common users</strong>, not <strong>local users</strong>.</p>
<p>Furthermore, the policies defined in the profile will be applied to all users of the PDB.</p>
<p>What parameters can be used? Unlike in the <strong>Profile</strong>, where we can assign a bunch of parameters for the setup, here we only have two parameters:</p>
<ul>
<li><p><strong>password_verify_function:</strong> To enforce password complexity using a function assigned to the <strong>Mandatory Profile</strong>. By default is <em>null</em>.</p>
</li>
<li><p><strong>password_grace_time</strong>: to set a grace period for accounts that are not compliant with mandatory password complexity rules. By default is <em>0</em>.</p>
</li>
</ul>
<p>First of all, let’s define a new function in order to assing <strong>password_verify_function.</strong></p>
<pre><code class="lang-sql">SQL&gt; 
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">OR</span> <span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">FUNCTION</span> VALIDATION_BUSINESS(username     <span class="hljs-built_in">varchar2</span>,
                                               <span class="hljs-keyword">password</span>     <span class="hljs-built_in">varchar2</span>,
                                               old_password <span class="hljs-built_in">varchar2</span>)
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">boolean</span> <span class="hljs-keyword">IS</span>
<span class="hljs-keyword">BEGIN</span>
  <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> ora_complexity_check(<span class="hljs-keyword">password</span>, chars =&gt; <span class="hljs-number">8</span>, digit =&gt; <span class="hljs-number">4</span>) <span class="hljs-keyword">then</span>
    <span class="hljs-keyword">return</span>(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>;
  return(true);
<span class="hljs-keyword">END</span>;
/
Function created.
</code></pre>
<p>As we can see, we have defined the <strong>VALIDATION_BUSINESS</strong> function within CDB$Root in order to validate that the user’s password has at least 8 characters “<em>chars =&gt; 8</em>” and 4 digits “<em>digit=&gt;4</em>“.</p>
<p>After that, let’s create the <strong>Mandatory Profile</strong> using the following parameters:</p>
<ul>
<li><p><em>PASSWORD_VERIFY_FUNCTION</em> To assign the previous function .</p>
</li>
<li><p><em>PASSWORD_GRACE_TIME</em> To set a 5‑day grace period for user accounts.</p>
</li>
</ul>
<pre><code class="lang-sql">SQL&gt; 
  <span class="hljs-keyword">CREATE</span> MANDATORY PROFILE C<span class="hljs-comment">##VALIDATION_BUSINESS </span>
   <span class="hljs-keyword">LIMIT</span> 
     <span class="hljs-keyword">PASSWORD_VERIFY_FUNCTION</span> VALIDATION_BUSINESS 
     <span class="hljs-keyword">PASSWORD_GRACE_TIME</span> <span class="hljs-number">5</span> 
   <span class="hljs-keyword">CONTAINER</span> = <span class="hljs-keyword">ALL</span>; 

Profile created.
</code></pre>
<p>As the last step, let’s upgrade the following parameter: <strong>MANDATORY_USER_PROFILE</strong>.</p>
<p>Here we have several options. On one hand, if we want to apply it to all PDBs, we need to make the change within CDB$ROOT. On the other hand, if we want to apply it to only one PDB, we need to make the change within that specific PDB.</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">show</span> parameter MANDATORY_USER_PROFILE
<span class="hljs-keyword">NAME</span>                                 <span class="hljs-keyword">TYPE</span>        <span class="hljs-keyword">VALUE</span>
<span class="hljs-comment">------------------------------------ ----------- ------------------------------</span>
mandatory_user_profile               <span class="hljs-keyword">string</span>

<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">SYSTEM</span> <span class="hljs-keyword">SET</span> MANDATORY_USER_PROFILE=C<span class="hljs-comment">##VALIDATION_BUSINESS;</span>
<span class="hljs-keyword">System</span> altered.

<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">show</span> parameter MANDATORY_USER_PROFILE

<span class="hljs-keyword">NAME</span>                                 <span class="hljs-keyword">TYPE</span>        <span class="hljs-keyword">VALUE</span>
<span class="hljs-comment">------------------------------------ ----------- ------------------------------</span>
mandatory_user_profile               <span class="hljs-keyword">string</span>      C<span class="hljs-comment">##VALIDATION_BUSINESS</span>
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[26ai] Oracle Temporary Tablespace Groups]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we’re going to talk about Temporary Tablespace Groups.
Even though It’s not a feature in 26ai, we’re going to set it up.
First of all, this type of tablespace allows users , when performing ope...]]></description><link>https://dbaintheshadow.com/26ai-oracle-temporary-tablespace-groups</link><guid isPermaLink="true">https://dbaintheshadow.com/26ai-oracle-temporary-tablespace-groups</guid><category><![CDATA[Oracle 26ai]]></category><category><![CDATA[pdb]]></category><category><![CDATA[temporal]]></category><category><![CDATA[groups]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Wed, 21 Jan 2026 07:07:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768949026630/a51b9914-ad81-4b3a-9eeb-18ec55618b42.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/26ai-oracle-temporary-tablespace-groups"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>Today, we’re going to talk about <strong>Temporary Table</strong><a target="_blank" href="https://dbaenlasombra.com/oci-proxy-pdb?showSharer=true"><strong>space Groups.</strong></a></p>
<p>Even though It’s not a feature in <strong>26ai,</strong> we’re going to set it up.</p>
<p>First of all, this type of tablespace allows users , when performing operations that need a large amount of temporary space, such as sorting, Oracle can distribute the workload across multiple temporary tablespaces, thereby avoiding saturation when relying on a single temporary tablespace.</p>
<p>In this lab, we will use the following:</p>
<ul>
<li><strong>Source</strong>: 26ai on VM DB System in Oracle Cloud (<em>test</em>).</li>
</ul>
<p>So, let's get down to business!</p>
<p><strong>Step 1:</strong> Create the PDB <strong>TEST</strong> on Source and check which temporary tablespace is assigned by default:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">SHOW</span> PDBS

    CON_ID CON_NAME                       <span class="hljs-keyword">OPEN</span> <span class="hljs-keyword">MODE</span>  <span class="hljs-keyword">RESTRICTED</span>
<span class="hljs-comment">---------- ------------------------------ ---------- ----------</span>
         <span class="hljs-number">3</span> <span class="hljs-keyword">TEST</span>                           <span class="hljs-keyword">READ</span> WRITE <span class="hljs-keyword">NO</span>

<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">Select</span> Property_Name, Property_Value 
     <span class="hljs-keyword">From</span> database_properties 
     <span class="hljs-keyword">Where</span> property_name = <span class="hljs-string">'DEFAULT_TEMP_TABLESPACE'</span>;

PROPERTY_NAME                                      PROPERTY_VALUE
<span class="hljs-comment">-------------------------------------------------- ----------------------------------------------------------------------------------------------------</span>
DEFAULT_TEMP_TABLESPACE                            TEMP
</code></pre>
<p><strong>Step 2:</strong> Let’s define a new temporary tablespace group with several temporary tablespaces. Oracle doesn’t provide a statement in order to create a tablespace group, we need to speficy it when creating the tablespace.</p>
<pre><code class="lang-sql"> SQL&gt; 
 <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TEMPORARY</span> <span class="hljs-keyword">TABLESPACE</span> GRP_TMP_TAB_1 TEMPFILE  <span class="hljs-keyword">SIZE</span> <span class="hljs-number">50</span>M <span class="hljs-keyword">TABLESPACE</span> <span class="hljs-keyword">GROUP</span> GRP_TMP;
  Tablespace created.
SQL&gt; 
 <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TEMPORARY</span> <span class="hljs-keyword">TABLESPACE</span> GRP_TMP_TAB_2 TEMPFILE  <span class="hljs-keyword">SIZE</span> <span class="hljs-number">50</span>M <span class="hljs-keyword">TABLESPACE</span> <span class="hljs-keyword">GROUP</span> GRP_TMP;
  Tablespace created.
</code></pre>
<p>We can chech the new temporary tablespace group in <strong>DBA_TABLESPACE_GROUPS</strong>:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">Select</span> * <span class="hljs-keyword">From</span> DBA_TABLESPACE_GROUPS ;

GROUP_NAME                     TABLESPACE_NAME
<span class="hljs-comment">------------------------------ ------------------------------</span>
GRP_TMP                        GRP_TMP_TAB_1
GRP_TMP                        GRP_TMP_TAB_2
</code></pre>
<p>In case we already have a temporary tablespace, or if we have created a new one without assigning it to a group, we can move it as follows:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TEMPORARY</span> <span class="hljs-keyword">TABLESPACE</span> GRP_TMP_TAB_3 TEMPFILE  <span class="hljs-keyword">SIZE</span> <span class="hljs-number">50</span>M ;

Tablespace created.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLESPACE</span> GRP_TMP_TAB_3 <span class="hljs-keyword">TABLESPACE</span> <span class="hljs-keyword">GROUP</span> GRP_TMP;

Tablespace altered.

SQL&gt;  <span class="hljs-keyword">Select</span> * <span class="hljs-keyword">From</span> DBA_TABLESPACE_GROUPS ;

GROUP_NAME                     TABLESPACE_NAME
<span class="hljs-comment">------------------------------ ------------------------------</span>
GRP_TMP                        GRP_TMP_TAB_1
GRP_TMP                        GRP_TMP_TAB_2
GRP_TMP                        GRP_TMP_TAB_3
</code></pre>
<p><strong>Step 3:</strong> Lastly, Let’s set our temporary tablespace group <strong>GRP_TMP</strong> as the <em>default temporary tablespace</em>.</p>
<pre><code class="lang-sql">SQL&gt;  <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">TEMPORARY</span> <span class="hljs-keyword">TABLESPACE</span> GRP_TMP;

Database altered.

SQL&gt; 
   <span class="hljs-keyword">Select</span> Property_Name, Property_Value 
   <span class="hljs-keyword">From</span> database_properties <span class="hljs-keyword">where</span> property_name = <span class="hljs-string">'DEFAULT_TEMP_TABLESPACE'</span>;

PROPERTY_NAME                                      PROPERTY_VALUE
<span class="hljs-comment">-------------------------------------------------- ----------------------------------------------------------------------------------------------------</span>
DEFAULT_TEMP_TABLESPACE                            GRP_TMP
</code></pre>
<p>When a temporary tablespace group is set as the default temporary tablespace, none of the temporary tablespace within the group can be dropped. If you need to drop one of them, you must first assign another temporary tablespace as the default..</p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[OCI] Proxy PDB]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we’re going to talk about Proxy PDB.
So, what is a Proxy PDB? Basically, it’s when one PDB references another PDB remotely, or even within the same CDB. It works like DB Links, but in this case...]]></description><link>https://dbaintheshadow.com/oci-proxy-pdb</link><guid isPermaLink="true">https://dbaintheshadow.com/oci-proxy-pdb</guid><category><![CDATA[#proxypdb]]></category><category><![CDATA[OCI]]></category><category><![CDATA[Oracle 23ai]]></category><category><![CDATA[pdb]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Tue, 13 Jan 2026 19:49:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768304798444/48770b0b-3f3d-4231-88b8-c9fedd511255.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/oci-proxy-pdb?showSharer=true"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>Today, we’re going to talk about <strong>Proxy PDB.</strong></p>
<p>So, <a target="_blank" href="https://dbaenlasombra.com/oci-26ai-refreshable-clone-pdbs?showSharer=true">what is a <strong>Prox</strong></a><strong>y PDB</strong>? Basically, it’s when one PDB references another PDB remotely, or even within the same CDB. It works like <strong>DB Links</strong>, but in this case, it’s not about a single table, it's about an entire PDB.</p>
<p>Here are some notes on this topic:</p>
<ul>
<li><p>The user must have the <strong><em>CREATE PLUGGABLE DATABASE</em></strong> privilege.</p>
</li>
<li><p>The PDB must be in <strong>local undo mode</strong>.</p>
</li>
<li><p>The PDB must be in <strong>ARCHIVELOG</strong> mode.</p>
</li>
<li><p>The reference PDB must be in <strong>OPEN READ WRITE</strong> mode before creating our the <strong>Proxy PDB</strong>. Once the <strong>Proxy PDB</strong> is created, we can change it.</p>
</li>
<li><p>We must create a <strong>DB Link</strong> in order to reference either the CDB or the PDB.</p>
</li>
</ul>
<p>In this lab, we will use the following::</p>
<ul>
<li><p><strong>Source</strong>: 26ai VM DB System Oracle Cloud (<em>test_ORI</em>).</p>
</li>
<li><p><strong>Target</strong>: 26ai VM DB System Oracle Cloud (<em>test_TARGET</em>).</p>
</li>
</ul>
<p>So, let's get down to business!</p>
<p><strong>Step 1</strong>: Let’s create the PDB PDB_DAVID on TEST_ORI:</p>
<pre><code class="lang-plaintext">SQL&gt; 
CREATE PLUGGABLE DATABASE PDB_DAVID ADMIN USER ADMIN 
  IDENTIFIED BY ADMIN keystore identified by external store;
Pluggable database created.
SQL&gt; ALTER PLUGGABLE DATABASE PDB_DAVID OPEN;
Pluggable database altered.
SQL&gt; ALTER PLUGGABLE DATABASE PDB_DAVID SAVE STATE;
Pluggable database altered.
SQL&gt; show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         4 PDB_DAVID                      READ WRITE NO
SQL&gt; ! hostname
source
</code></pre>
<p><strong>Step 2</strong>: Let’s create a <strong>common user</strong>, not a <strong>local user</strong>, on both machines. In this case, the DBA role includes the <em>CREATE SESSION</em> and <em>CREATE PLUGGABLE DATABASE</em> privileges.</p>
<pre><code class="lang-plaintext">SQL&gt; CREATE USER C##MANAGER IDENTIFIED BY "XXXXXXX";
User created.
SQL&gt; GRANT RESOURCE, DBA, UNLIMITED TABLESPACE TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
</code></pre>
<p><strong>Step 3</strong>: We’re going to check that the PDB is using <strong>local undo mode</strong>.</p>
<pre><code class="lang-plaintext">SQL&gt; r
  1* Select property_name, property_value 
       From database_properties 
      Where property_name='LOCAL_UNDO_ENABLED'

PROPERTY_NAME        PROPERTY_VALUE
-------------------- ----------------------------------------
LOCAL_UNDO_ENABLED   TRUE
</code></pre>
<p><strong>Step 4</strong>: Let’s create the <strong>DB Links</strong> on the target. In this case, we’re going to use <strong>easy connect</strong> instead of <strong>local naming</strong>:</p>
<pre><code class="lang-plaintext">SQL&gt; 
CREATE DATABASE LINK SOURCE_PROXY CONNECT TO C##MANAGER 
  IDENTIFIED BY "XXXXX" 
    USING 'source:1521/pdb_david.XXXXXXXXXXXXXXXX';

Database link created.

SQL&gt; 
SQL&gt;  SELECT * FROM DUAL@SOURCE_PROXY;

D
-
X
</code></pre>
<p><strong>Step 5</strong>: Let’s create our PDB using the <strong>AS PROXY</strong> clause in order to indicate that it’s a <strong>Proxy PDB</strong>, and the <strong>FROM</strong> clause in order to specify the referenced PDB.</p>
<pre><code class="lang-plaintext">SQL&gt; 
CREATE PLUGGABLE DATABASE PDB_DAVID AS PROXY 
  FROM PDB_DAVID@SOURCE_PROXY keystore identified by external store;
Pluggable database created.
SQL&gt; alter pluggable database pdb_david open;
Pluggable database altered.
SQL&gt; show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB_DAVID                      READ WRITE NO

SQL&gt; r
  1  SELECT pdb_name, is_proxy_pdb
  2* FROM   cdb_pdbs

PDB_NAME                       IS_PROXY_PDB
------------------------------ ----------------------------------------
PDB$SEED                       NO
PDB_DAVID                      YES
</code></pre>
<p>Here are some key considerations:</p>
<ul>
<li><strong>V$PROXY_PDB_TARGETS:</strong> The view shows information about the details of the target for a proxy PDB.</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; r
  1* select * from v$proxy_pdb_targets

    CON_ID TARGET_PORT TARGET_HOST          TARGET_SERVICE                                                                   TARGET_USER
---------- ----------- -------------------- -------------------------------------------------------------------------------- --------------------
         3        1521 source               4843e8f3860c707be063cfdf680abf32.XXXXXXX.XXXXXXX.XXXXXXX.com
</code></pre>
<ul>
<li><p>The <strong>SYSTEM</strong> and <strong>SYSAUX</strong> tablespaces are copied and synchronized with the source.</p>
</li>
<li><p>Only <strong>password authentication</strong> is supported, not <strong>OS authentication</strong>. Below, you can see how both authentication methods work.</p>
</li>
</ul>
<pre><code class="lang-plaintext">[oracle@target ~]$ sqlplus / as sysdba
Connected to:
Oracle AI Database 26ai EE High Perf Release 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
Version 23.26.0.0.0
SQL&gt; alter session set container= PDB_DAVID;
Session altered.
SQL&gt;  Select * From C##MANAGER.CODIGO_POSTAL;
 Select * From C##MANAGER.CODIGO_POSTAL
                          *
ERROR at line 1:
ORA-00942: table or view "C##MANAGER"."CODIGO_POSTAL" does not exist
Help: https://docs.oracle.com/error-help/db/ora-00942/

SQL&gt; conn C##MANAGER/"XXXXXX"@'target:1521/pdb_david.XXXXX.XXXXX.XXXXXX.com'
Connected.
SQL&gt;  Select * From C##MANAGER.CODIGO_POSTAL;

ID    POBLACION                                                                                            PAIS
----- ---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
46000 Valencia                                                                                             Espa??a
08000 Barcelona                                                                                            Espa??a
28000 Madrid                                                                                               Espa??a
55500 Wisconsin                                                                                            U.S.A.
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[OCI-26ai] Refreshable Clone PDBs]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, we’re going to talk about how to make a copy a PDB and keep the copy up-to-date.
This kind of migration migth be local (same CDB) or remotely (another CDB).
Let’s start with the type of remotel...]]></description><link>https://dbaintheshadow.com/oci-26ai-refreshable-clone-pdbs</link><guid isPermaLink="true">https://dbaintheshadow.com/oci-26ai-refreshable-clone-pdbs</guid><category><![CDATA[OCI]]></category><category><![CDATA[pdb]]></category><category><![CDATA[#refresh]]></category><category><![CDATA[Oracle 26ai]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Tue, 23 Dec 2025 15:21:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766420222465/a4beca60-a42d-41d7-a871-9f8e09a6c207.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/oci-26ai-refreshable-clone-pdbs?showSharer=true"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>Today, we’re going to talk about how to make a copy a PDB and keep the copy up-to-date.</p>
<p>This kind of migration migth be <strong>local</strong> (same CDB) or <strong>remotely</strong> (another CDB).</p>
<p>Let’s start with the type of remotely.</p>
<p>Another important point , let’s use the <strong>external store</strong> in order to create PDBs (we need to set up SEPS). In the next article, we’ll set up SEPS.</p>
<p>In this lab, we will use the following:</p>
<ul>
<li><p><strong>Source</strong>: 26ai on VM DB System in Oracle Cloud (test_ORI).</p>
</li>
<li><p><strong>Target</strong>: 26ai on VM DB System in Oracle Cloud (test_TARGET).</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766234418615/7af4855c-a9fd-42fd-8227-5b195d359ea8.png" alt class="image--center mx-auto" /></p>
<p>And the model is as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766234319392/ee0c4aa8-31b2-48bd-8f0b-05c4e91b44c3.png" alt class="image--center mx-auto" /></p>
<ul>
<li><strong>Step 1:</strong>: Create the PDB <strong>REFRESH_PDB</strong> on <em>TEST_ORI</em>:</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; CREATE PLUGGABLE DATABASE REFRESH_PDB ADMIN USER admin IDENTIFIED BY admin  keystore identified by external store; 
Pluggable database created.
SQL&gt; ALTER PLUGGABLE DATABASE REFRESH_PDB OPEN;
Pluggable database altered.
SQL&gt; ALTER PLUGGABLE DATABASE REFRESH_PDB SAVE STATE;
Pluggable database altered.
SQL&gt; SHOW PDBS

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         4 REFRESH_PDB                    READ WRITE NO
SQL&gt; ! hostname
source
</code></pre>
<ul>
<li><strong>Step 2:</strong>: Let’s check that there aren’t other PDB, only <em>PDB$SEED on TEST_TARGET</em>.</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
SQL&gt; ! hostname
target
</code></pre>
<ul>
<li><strong>Step 3</strong>: Let’s create a <strong>common user</strong>, not a <strong>local user</strong>. The user must have the same name and password.</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; CREATE USER C##MANAGER IDENTIFIED BY "XXXXXX";
User created.
SQL&gt; GRANT CREATE SESSION, RESOURCE, CREATE ANY TABLE, UNLIMITED TABLESPACE TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
SQL&gt; GRANT CREATE PLUGGABLE DATABASE TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
SQL&gt; GRANT SYSOPER TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
</code></pre>
<ul>
<li><strong>Step 4</strong>: Let’s create a <strong>DB Links</strong>. Before doing so, we need to modify both <em>tnsnames</em> files .</li>
</ul>
<p>Source:</p>
<pre><code class="lang-plaintext">SQL&gt; ! hostname
source

SQL&gt; ! tail -8  $ORACLE_HOME/network/admin/tnsnames.ora
TARGET =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXXXXXXXXXXXXXXXXX)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XXXXXXXXXXXXXXXXXXXX)
    )
  )
</code></pre>
<p>Target:</p>
<pre><code class="lang-plaintext">SQL&gt; ! hostname
target
SQL&gt; ! tail -8  $ORACLE_HOME/network/admin/tnsnames.ora
SOURCE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXXXXXXXXXXXXXXXXX)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XXXXXXXXXXXXXXXXXXXX)
    )
  )
</code></pre>
<p>At this point, let’s create the DB Link on both.</p>
<pre><code class="lang-plaintext">SQL&gt; CREATE DATABASE LINK DB_Source CONNECT TO C##MANAGER IDENTIFIED BY "XXXXXXXXX" USING 'SOURCE';
Database link created.
SQL&gt; Select * From Dual@DB_Source;
D
-
X
</code></pre>
<p>Moreover, we need to verify that the <strong>DB Link</strong> is working.</p>
<p>Lastly, let’s create a table with some data since our pdb is empty.</p>
<pre><code class="lang-plaintext">SQL&gt; alter session set container=REFRESH_PDB;
Session altered.
SQL&gt; CREATE TABLE C##MANAGER.COPY_NUMERICOS AS 
     SELECT ROWNUM NUM 
       FROM DUAL 
    CONNECT BY ROWNUM &lt;= 1000000;

Table created.
</code></pre>
<ul>
<li><strong>Step 5</strong>: Let’s clone our PDB using the <em>external store</em> :</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; CREATE PLUGGABLE DATABASE REFRESH_PDB FROM REFRESH_PDB@DB_Source REFRESH MODE MANUAL keystore identified by external store;

Pluggable database created.
</code></pre>
<p>In this case, our PDB is the kind of <strong>REFRESH MODE MANUAL</strong>.</p>
<p>When we defined our PDB with <strong>REFRESH MODE MANUAL</strong>, it means the information isn’t automatically, but if we define it as <strong>REFRESH MODE EVERY &lt;min&gt;</strong>, the PDB will refresh automatically at the specified interval.</p>
<p>Currently, the PDB state is <strong>REFRESHING</strong>.</p>
<pre><code class="lang-plaintext">SQL&gt; select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME             STATUS               REFRESH_MODE         REFRESH_INTERVAL
---------- -------------------- -------------------- -------------------- ----------------
         3 REFRESH_PDB          REFRESHING           MANUAL
</code></pre>
<p>Let’s open the PDB in read-only mode and verify that the table with the data exists.</p>
<pre><code class="lang-plaintext">SQL&gt; ALTER SESSION SET CONTAINER=REFRESH_PDB;
Session altered.
SQL&gt; ALTER PLUGGABLE DATABASE OPEN READ ONLY;
Pluggable database altered.
SQL&gt; SELECT COUNT(*) FROM C##MANAGER.COPY_NUMERICOS;

  COUNT(*)
----------
   1000000
</code></pre>
<p>Next, we insert information into the table and refresh the PDB.</p>
<pre><code class="lang-plaintext"> SQL&gt; ALTER PLUGGABLE DATABASE CLOSE IMMEDIATE;

Pluggable database altered.

SQL&gt; ALTER PLUGGABLE DATABASE REFRESH;

Pluggable database altered.

SQL&gt; ALTER PLUGGABLE DATABASE OPEN READ ONLY;

Pluggable database altered.

SQL&gt;  SELECT COUNT(*) FROM C##MANAGER.COPY_NUMERICOS;

  COUNT(*)
----------
   2000000
</code></pre>
<p>Great!, Both PDBs are synchronized.</p>
<p>At this point, we can either finished or switch the roles.</p>
<ul>
<li><strong>Finished</strong>: Our PDB will change from a <strong>refreshable clone</strong> to a <strong>regular PDB</strong>.</li>
</ul>
<pre><code class="lang-plaintext">SQL&gt; ALTER PLUGGABLE DATABASE CLOSE IMMEDIATE;
Pluggable database altered.
SQL&gt;  alter pluggable database refresh mode none;
Pluggable database altered.
SQL&gt; ALTER PLUGGABLE DATABASE OPEN;
Pluggable database altered.

SQL&gt; select con_id, pdb_name, status, refresh_mode, refresh_interval 
     from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME             STATUS               REFRESH_MODE         REFRESH_INTERVAL
---------- -------------------- -------------------- -------------------- ----------------
         3 REFRESH_PDB          NORMAL               NONE
</code></pre>
<ul>
<li><strong>Switch the roles:</strong> our <em>source PDB</em> will change from <strong>normal</strong> to <strong>refreshing</strong>, and <em>target PDB</em> will change from <strong>refreshing</strong> to <strong>normal</strong> mode:</li>
</ul>
<p>Source:</p>
<pre><code class="lang-plaintext">SQL&gt; col pdb_name format a15
SQL&gt;  set linesize 1000
SQL&gt; select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
---------- --------------- ---------- ------ ----------------
         4 REFRESH_PDB     NORMAL     NONE

SQL&gt; ALTER SESSION SET CONTAINER = REFRESH_PDB;                                                                 

Session altered.

SQL&gt;  ALTER PLUGGABLE DATABASE REFRESH MODE MANUAL FROM REFRESH_PDB@DB_Target SWITCHOVER;

Pluggable database altered.

SQL&gt; alter pluggable database open read only;

Pluggable database altered.

SQL&gt; select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
---------- --------------- ---------- ------ ----------------
         4 REFRESH_PDB     REFRESHING MANUAL
</code></pre>
<p>Target:</p>
<pre><code class="lang-plaintext">SQL&gt; r
  1* select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB'

    CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
---------- --------------- ---------- ------ ----------------
         3 REFRESH_PDB     REFRESHING MANUAL

SQL&gt; alter pluggable database refresh_pdb open read only;

Pluggable database altered.

SQL&gt; select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
---------- --------------- ---------- ------ ----------------
         3 REFRESH_PDB     NORMAL     NONE
</code></pre>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[OCI] Resource Scheduler]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
One of the most important aspects when we are an architect on OCI, it is goes hand in hand with the customer in order to save money when we have to define resources in the tenancy.
Since May 2024, OCI...]]></description><link>https://dbaintheshadow.com/oci-resource-scheduler</link><guid isPermaLink="true">https://dbaintheshadow.com/oci-resource-scheduler</guid><category><![CDATA[switchon]]></category><category><![CDATA[switchoff]]></category><category><![CDATA[OCI]]></category><category><![CDATA[schedule]]></category><category><![CDATA[instance]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Sat, 25 Oct 2025 12:09:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761299511930/63597971-1057-4d13-bb19-5fcb94edc9e4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/oci-resource-scheduler"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p><a target="_blank" href="https://dbaenlasombra.com/23ai-shadow-tablespaces">One of the mo</a>st important aspects when we are an architect on OCI, it is goes hand in hand with the customer in order to save money when we have to define resources in the <strong>tenancy</strong>.</p>
<p>Since <em>May 2024</em>, OCI has released the service “<strong>OCI resource scheduler</strong>“ in order to make us this task easier for us. Before then, this task could be done using methods such as:</p>
<ul>
<li><p><strong>Crontab</strong>. Nowadays, we always have an environment running every day without interruptions. This environment was ideal for setting up a shell script using cron under the <strong>opc</strong> user.</p>
<p>  Below, you can see an example using this configuration:</p>
</li>
</ul>
<pre><code class="lang-bash">[opc ~]$ crontab -l
 30 7 * * 1,2,3,4,5 /home/opc/dbsystem/start_dbsystem.sh &gt;&gt; /home/opc/dbsystem/start_dbsystem.log
[opc ~]$ cat /home/opc/dbsystem/start_dbsystem.sh
<span class="hljs-comment">#!/bin/bash</span>
<span class="hljs-built_in">cd</span> /home/opc/dbsystem 

NODE_SWITCH=&lt;OCID&gt;

. ./oci-curl.sh

oci-curl &lt;END_POINT&gt; POST ./empty.json /20160918/dbNodes/<span class="hljs-variable">${NODE_SWITCH}</span>?action=start
</code></pre>
<ul>
<li><p><strong>Auto Scaling</strong> in OCI by <strong>Richard Garsthagen.</strong> He published a repository on github under the name <strong>OCI-AutoScale</strong> (<a target="_blank" href="https://github.com/AnykeyNL/OCI-AutoScale">link repositorio</a>) in order to make these operations using <strong>tags.</strong></p>
<p>  When you set up <strong>OCI-AutoScale</strong>, one of the step, it’s configurate the tag <strong>Schedule:</strong></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761066421080/8d6ff26f-6b78-4e54-b088-13fb3fa38783.png" alt class="image--center mx-auto" /></p>
<p>  The next step would be to assign these tags to an instance:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761067383472/96de0ce7-76eb-4820-82d4-11b573cd26d2.png" alt class="image--center mx-auto" /></p>
<p>  In this example, we have assigned several tags:</p>
<ul>
<li><p><strong>Weekend</strong>: Shut down all weekend.</p>
</li>
<li><p><strong>WeekDay</strong>: Switch on some hours on weekdays. We can see the translation of “<em>0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0</em>” on the left slide.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-oci-resource-scheduler"><strong>OCI resource scheduler</strong></h3>
<p>These are the steps that we’re going to follow in order to use the <strong>Resource Scheduler</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761387863048/ffd415f9-d68c-46cc-8f9a-07db0217a2a4.png" alt class="image--center mx-auto" /></p>
<p>Before getting our hands dirty,we need to check as follows:</p>
<ul>
<li><p>Our user has the necessary permissions in order to create <strong>schedules</strong>.</p>
<pre><code class="lang-bash">  Allow any-user to manage resource-schedule-family <span class="hljs-keyword">in</span> tenancy
</code></pre>
</li>
<li><p>The <strong>schedule</strong> has the necessary permissions in order to manage resources within the tenancy:</p>
<pre><code class="lang-bash">  Allow any-user to manage all-resources 
   <span class="hljs-keyword">in</span> compartment <span class="hljs-string">'&lt;compartment&gt;'</span> <span class="hljs-built_in">where</span> all{request.principal.type=<span class="hljs-string">'resourceschedule'</span>}
</code></pre>
</li>
<li><p>We are going to create a new instance in order to check the new <strong>schedule</strong>:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761309231714/fa4001f0-9076-44fb-9128-e780c10f21a2.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p>After doing all these steps, we are ready. So, let's get down to business!</p>
<p>Let’s go to the section “<strong>Governance &amp; Administration</strong>” and <strong>Schedules</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761068526472/9929d499-5f66-4a50-acda-833868cecc06.png" alt class="image--center mx-auto" /></p>
<p>Here, we can see the <strong>Resource scheduler</strong> section. Click on “<strong>Create a schedule</strong>”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761309011547/f1b235c8-5c07-47e5-b497-8072938b0205.png" alt class="image--center mx-auto" /></p>
<p>In the first section, we are going to provide the basic information such as <strong>name</strong> or <strong>action</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761121076288/22ac80c3-37ba-49c2-b89a-a253255b91c8.png" alt class="image--center mx-auto" /></p>
<p>In the second section, we are going to select the resource on which we want make the action:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761121425419/0d50bdf6-6c94-4f46-a2d8-d84085a17919.png" alt class="image--center mx-auto" /></p>
<p>Here, we can see a filter with two options: <strong>Static</strong> or <strong>Dynamic</strong>.</p>
<p>The differences are as follows:</p>
<ul>
<li><p><strong>Static</strong>: This is when we define a schedule for a single resource.</p>
</li>
<li><p><strong>Dynamic:</strong> This is when we define a schedule for a group of resources. Moreover, when using Dynamic method, the current set of resources that match the criteria is displayed for reference.</p>
<ul>
<li><p><em>Tag:</em> By selecting tag method, you can search for resources using it*.*</p>
</li>
<li><p><em>Resource Type</em>: You can find resources such as <em>instance</em>, <em>instance pool</em>, <em>autonomous database</em>, <em>function or even DB system</em>.</p>
</li>
<li><p><em>Compartment:</em> You can locate resources in one compartment or across all compartments*.*</p>
</li>
<li><p><em>Status</em>: By selecting the status method, you can search for resources using their status. The states are available, running, stopped or all.</p>
</li>
</ul>
</li>
</ul>
<p>In this case, we select the <strong>static</strong> option and click on our instance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761229546582/04090d6d-5cd1-492f-841c-535a9d6cfec7.png" alt class="image--center mx-auto" /></p>
<p>In the next step, we will be able to add parameters to our resource,but in this case, it does not apply.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761229642165/3d8f9104-96b9-4a2d-940e-08fb1a3982d7.png" alt class="image--center mx-auto" /></p>
<p>The next step is the most important, because we have to define the schedule in order to switch on the instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761168926242/91b09e8b-7e19-46b8-9176-0532bc4c6a56.png" alt class="image--center mx-auto" /></p>
<p>First, we define the schedule using either the “<strong>Form Interface”</strong> or a “<strong>Cron expression”</strong>. In this case, since we define a couple of schedules, we will use both options.</p>
<p>Let’s click on “<strong>Cron expression</strong>” in order to switch on our instance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761390901305/08410e3a-43ae-4c5f-8c59-c378edfcbd11.png" alt class="image--center mx-auto" /></p>
<p>Here, we can see as follows:</p>
<ul>
<li><p><strong>Recurrence details</strong>: A little description, it’s optional except in this case. Watch out! when we use <strong>cron</strong>, we should fill in this field with a <strong>Cron expression</strong>.</p>
<p>  If you don’t fill in this field, you will see the following error:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761171906611/e9bee26a-4174-4bcb-92ae-4b48db164b46.png" alt /></p>
<p>  Our <strong>Cron expression</strong> is: “<em>30 12 \</em> * *<em>“ **</em>.<em>*</em></p>
</li>
<li><p><strong>Time</strong>: UTC time in 24-hour format.</p>
</li>
<li><p><strong>Start date</strong>: Enter a date in order to specify the start date.</p>
</li>
<li><p><strong>End date</strong>: Enter a date in order to specify the end date, it’s optional.</p>
</li>
</ul>
<p>The last window, it would be a summary our schedule.</p>
<p>Let’s define the <strong>schedule</strong> in order to switch off our instance. All steps will be the same as in the previous schedule, except when we define the schedule, because we use the option “<strong>Form Interface</strong>”.</p>
<p>Here’s our schedule:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761392305970/8afad909-ad45-4f2d-88cb-867c27c4d3b2.png" alt class="image--center mx-auto" /></p>
<p>Ready! With all steps completed, we now have both schedules prepared in order to switch on/switch off our instance.</p>
<p>Moreover, if we go back to the beginning, you will see that both schedules are working.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761392915448/08e0f6c3-0336-4909-aa71-4fe3b1d07bf9.png" alt class="image--center mx-auto" /></p>
<p>Looking forward to seeing you in the next article :)</p>
]]></content:encoded></item><item><title><![CDATA[[23ai] Shadow Tablespaces]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
The otherr day, while I was reading the Oracle’s website, I came across a type of tablespace that I wasn’t familiar with. It’s called “Shadow Tablespaces”.
It’s not a feature in 23ai, so it was introd...]]></description><link>https://dbaintheshadow.com/23ai-shadow-tablespaces</link><guid isPermaLink="true">https://dbaintheshadow.com/23ai-shadow-tablespaces</guid><category><![CDATA[shadowtablespace]]></category><category><![CDATA[cdbroot]]></category><category><![CDATA[Oracle 23ai]]></category><category><![CDATA[lost]]></category><category><![CDATA[pdb]]></category><category><![CDATA[multitenant]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Sat, 04 Oct 2025 17:18:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759592203272/c9ba4cd8-f797-4c01-ba83-15e6613a8ee5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/23ai-shadow-tablespaces"><strong><em>Spanish version</em></strong></a><em>.</em></p>
<p>The otherr day, while I was reading the Oracle’s website<a target="_blank" href="https://dbaenlasombra.com/ogg-lentitud-de-replicat">,</a> I came across a type of tablespace that I wasn’t familiar with. It’s called “<strong>Shadow Tablespaces”</strong>.</p>
<p>It’s not a feature in <strong>23ai,</strong> so it was introduced in <strong>18c</strong>.</p>
<p>Before we get our hands dirty with a small example, I want to clarify that <strong>Shadow tablespace</strong> is not related to the parameter <em>DB_LOST_WRITE_PROTECT</em>.</p>
<h2 id="heading-purpose"><strong>Purpose</strong></h2>
<p><strong>Shadow Tablespace</strong> is a kind of <strong><em>tablespace</em></strong>. In 23ai,it’s always bigfile. It provides fast detection againts lost writes for <strong><em>tablespaces</em></strong> or <strong><em>datafiles</em></strong>, minimize the time required in order to repair a database.</p>
<h2 id="heading-how-does-a-shadow-tablespace-work">How does a Shadow Tablespace work?</h2>
<p>In order to use this functionality, we need both a <strong>shadow tablespace</strong> and <strong>non-shadow tablespace</strong>.</p>
<p>Let’s check the following figure:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759578208948/10488d8d-3acd-46d3-b3ee-43fec08a70d1.png" alt class="image--center mx-auto" /></p>
<p>Here, we can see that the <strong>shadow tablespace “<em>STTab001</em>”</strong> tracks several <strong>tablespaces.</strong> These tablespaces are different: on one hand, one is a <strong>bigfile</strong> tablespace <strong>“<em>Tab002</em>”</strong>, and on the other hand, the other is a <strong>smallfile</strong> tablespace <strong>“<em>SmallTab001</em>”.</strong></p>
<p>How come both tablespaces are different? Because I want to show you how this functionality can be used at different levels: tablespace and datafile.</p>
<p>So, let's get down to business!</p>
<p>Let’s set up our PDB.</p>
<p>First of all, we’re going to create the “<strong>shadow tablespace“</strong> before enabling it. This step is very important because if we enable before creating the tablespace, we will receive the following error:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>
*
<span class="hljs-keyword">ERROR</span> <span class="hljs-keyword">at</span> line <span class="hljs-number">1</span>:
ORA<span class="hljs-number">-65491</span>: A lost write <span class="hljs-keyword">bigfile</span> <span class="hljs-keyword">tablespace</span> must exist <span class="hljs-keyword">before</span> attempting <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> lost write.
<span class="hljs-keyword">Help</span>: https://docs.oracle.com/<span class="hljs-keyword">error</span>-<span class="hljs-keyword">help</span>/db/ora<span class="hljs-number">-65491</span>/
</code></pre>
<p>Let’s create the tablespace <em>STTab001</em>:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">BIGFILE</span> <span class="hljs-keyword">TABLESPACE</span> STTab001 <span class="hljs-keyword">DATAFILE</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">10</span>M LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Tablespace created.
</code></pre>
<p>After that, we enable shadow lost write protection for the PDB:</p>
<pre><code class="lang-sql">SQL&gt; r
  1* <span class="hljs-keyword">select</span> PROPERTY_NAME, PROPERTY_VALUE <span class="hljs-keyword">from</span> database_properties <span class="hljs-keyword">where</span> PROPERTY_NAME=<span class="hljs-string">'NEW_LOST_WRITE'</span>

<span class="hljs-keyword">no</span> <span class="hljs-keyword">rows</span> selected

<span class="hljs-keyword">SQL</span>&gt;  <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Pluggable database altered.

SQL&gt; r
  1* <span class="hljs-keyword">select</span> PROPERTY_NAME, PROPERTY_VALUE <span class="hljs-keyword">from</span> database_properties <span class="hljs-keyword">where</span> PROPERTY_NAME=<span class="hljs-string">'NEW_LOST_WRITE'</span>

PROPERTY_NAME        PROPERTY_VALUE
<span class="hljs-comment">-------------------- --------------------</span>
NEW_LOST_WRITE       <span class="hljs-literal">TRUE</span>
</code></pre>
<p>If we had tried to enable from <strong>CDB$Root</strong> in order to apply it to all PDB**,** we would have received the following error:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">alter</span> <span class="hljs-keyword">session</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">container</span>=cdb$root;

Session altered.

SQL&gt; <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">BIGFILE</span> <span class="hljs-keyword">TABLESPACE</span> STTab001 <span class="hljs-keyword">DATAFILE</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">10</span>M LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Tablespace created.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>
*
<span class="hljs-keyword">ERROR</span> <span class="hljs-keyword">at</span> line <span class="hljs-number">1</span>:
ORA<span class="hljs-number">-65046</span>: operation <span class="hljs-keyword">not</span> allowed <span class="hljs-keyword">from</span> outside a <span class="hljs-keyword">pluggable</span> <span class="hljs-keyword">database</span>
<span class="hljs-keyword">Help</span>: https://docs.oracle.com/<span class="hljs-keyword">error</span>-<span class="hljs-keyword">help</span>/db/ora<span class="hljs-number">-65046</span>/
</code></pre>
<p>Let’s create both tablespaces:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">BIGFILE</span>   <span class="hljs-keyword">TABLESPACE</span> Tab002 <span class="hljs-keyword">DATAFILE</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">10</span>M;
Tablespace created.

SQL&gt; <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">SMALLFILE</span> <span class="hljs-keyword">TABLESPACE</span> SmallTab001 <span class="hljs-keyword">DATAFILE</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">1</span>M ;
Tablespace created.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLESPACE</span> SmallTab001 <span class="hljs-keyword">ADD</span> <span class="hljs-keyword">DATAFILE</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">1</span>M: 
<span class="hljs-keyword">Tablespace</span> altered.
</code></pre>
<p>Let’s verify the previous step:</p>
<pre><code class="lang-sql">SQL&gt; r
  <span class="hljs-keyword">Select</span> tablespace_name, <span class="hljs-keyword">contents</span>, lost_write_protect <span class="hljs-keyword">from</span> dba_tablespaces

TABLESPACE_NAME                <span class="hljs-keyword">CONTENTS</span>              LOST_WR
<span class="hljs-comment">------------------------------ --------------------- -------</span>
<span class="hljs-keyword">SYSTEM</span>                         <span class="hljs-keyword">PERMANENT</span>             <span class="hljs-keyword">OFF</span>
<span class="hljs-keyword">SYSAUX</span>                         <span class="hljs-keyword">PERMANENT</span>             <span class="hljs-keyword">OFF</span>
UNDOTBS1                       <span class="hljs-keyword">UNDO</span>                  <span class="hljs-keyword">OFF</span>
TEMP                           <span class="hljs-keyword">TEMPORARY</span>             <span class="hljs-keyword">OFF</span>
<span class="hljs-keyword">USERS</span>                          <span class="hljs-keyword">PERMANENT</span>             <span class="hljs-keyword">OFF</span>
STTAB001                       LOST WRITE <span class="hljs-keyword">PROTECTION</span> <span class="hljs-keyword">OFF</span>
TAB002                         <span class="hljs-keyword">PERMANENT</span>             <span class="hljs-keyword">OFF</span>
SMALLTAB001                    <span class="hljs-keyword">PERMANENT</span>             <span class="hljs-keyword">OFF</span>

<span class="hljs-keyword">SQL</span>&gt; r
  <span class="hljs-number">1</span>   <span class="hljs-keyword">Select</span> Tablespace_Name,LOST_WRITE_PROTECT ,File_Name, File_Id
  <span class="hljs-number">2</span>     <span class="hljs-keyword">From</span> Dba_Data_Files
  <span class="hljs-number">3</span>    <span class="hljs-keyword">Where</span> Tablespace_Name <span class="hljs-keyword">in</span> (<span class="hljs-string">'STTAB001'</span>,<span class="hljs-string">'TAB002'</span>,<span class="hljs-string">'SMALLTAB001'</span>)
  <span class="hljs-number">4</span>*  <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> file_id

TABLESPACE_NAME                LOST_WR FILE_NAME                                                                                               FILE_ID
<span class="hljs-comment">------------------------------ ------- ---------------------------------------------------------------------------------------------------- ----------</span>
STTAB001                       <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/sttab001<span class="hljs-number">.280</span><span class="hljs-number">.1213616675</span>                       <span class="hljs-number">13</span>
TAB002                         <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/tab002<span class="hljs-number">.281</span><span class="hljs-number">.1213625663</span>                         <span class="hljs-number">14</span>
SMALLTAB001                    <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/smalltab001<span class="hljs-number">.282</span><span class="hljs-number">.1213625677</span>                    <span class="hljs-number">15</span>
SMALLTAB001                    <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/smalltab001<span class="hljs-number">.283</span><span class="hljs-number">.1213625699</span>                    <span class="hljs-number">16</span>
</code></pre>
<p>Now, let’s enable <strong>Shadow Lost Write Protection</strong> for the tablespace “<em>TAB002”</em> and the datafile “<em>SMALLTAB001”</em>:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLESPACE</span> TAB002 <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Tablespace altered.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">DATAFILE</span> <span class="hljs-string">'+DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699'</span> <span class="hljs-keyword">ENABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Database altered.
</code></pre>
<p>Let’s verify again:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">Select</span> tablespace_name, <span class="hljs-keyword">contents</span>, lost_write_protect <span class="hljs-keyword">from</span> dba_tablespaces;

TABLESPACE_NAME                CONTENTS              LOST_WR
<span class="hljs-comment">------------------------------ --------------------- -------</span>
SYSTEM                         PERMANENT             OFF
SYSAUX                         PERMANENT             OFF
UNDOTBS1                       UNDO                  OFF
TEMP                           TEMPORARY             OFF
USERS                          PERMANENT             OFF
STTAB001                       LOST WRITE PROTECTION OFF
TAB002                         PERMANENT             ENABLED
SMALLTAB001                    PERMANENT             OFF

8 rows selected.

SQL&gt; r
  1   <span class="hljs-keyword">Select</span> Tablespace_Name,LOST_WRITE_PROTECT ,File_Name, File_Id
  <span class="hljs-number">2</span>     <span class="hljs-keyword">From</span> Dba_Data_Files
  <span class="hljs-number">3</span>    <span class="hljs-keyword">Where</span> Tablespace_Name <span class="hljs-keyword">in</span> (<span class="hljs-string">'STTAB001'</span>,<span class="hljs-string">'TAB002'</span>,<span class="hljs-string">'SMALLTAB001'</span>)
  <span class="hljs-number">4</span>*  <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> file_id

TABLESPACE_NAME                LOST_WR FILE_NAME                                                                                               FILE_ID
<span class="hljs-comment">------------------------------ ------- ---------------------------------------------------------------------------------------------------- ----------</span>
STTAB001                       <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/sttab001<span class="hljs-number">.280</span><span class="hljs-number">.1213616675</span>                       <span class="hljs-number">13</span>
TAB002                         ENABLED +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/tab002<span class="hljs-number">.281</span><span class="hljs-number">.1213625663</span>                         <span class="hljs-number">14</span>
SMALLTAB001                    <span class="hljs-keyword">OFF</span>     +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/smalltab001<span class="hljs-number">.282</span><span class="hljs-number">.1213625677</span>                    <span class="hljs-number">15</span>
SMALLTAB001                    ENABLED +<span class="hljs-keyword">DATA</span>/DB23AI_FWX_MAD/<span class="hljs-number">4004456</span>EB4523134E0634C00000AA230/<span class="hljs-keyword">DATAFILE</span>/smalltab001<span class="hljs-number">.283</span><span class="hljs-number">.1213625699</span>                    <span class="hljs-number">16</span>
</code></pre>
<p>As you can see, it’s very easy to enable it.</p>
<p>However, if you need to disabled it, you should do the following:</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLESPACE</span> TAB002 REMOVE LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Tablespace altered.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">DATAFILE</span> <span class="hljs-string">'+DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699'</span> <span class="hljs-keyword">SUSPEND</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Pluggable database altered.

SQL&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">PLUGGABLE</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">DISABLE</span> LOST WRITE <span class="hljs-keyword">PROTECTION</span>;

Pluggable database altered.

SQL&gt; <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLESPACE</span> STTAB001 <span class="hljs-keyword">INCLUDING</span> <span class="hljs-keyword">CONTENTS</span> <span class="hljs-keyword">AND</span> <span class="hljs-keyword">DATAFILES</span>;

Tablespace dropped.
</code></pre>
<p>Looking forward to seeing you in the next article.</p>
]]></content:encoded></item><item><title><![CDATA[[OGG] Replicat is running too slowly]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
Today, let’s look at a case where the Replicat process is running too slowly.
The situation with OGG when they notified me was as follows:
GGSCI 1> info all

Program     Status      Group       Lag at...]]></description><link>https://dbaintheshadow.com/ogg-replicat-is-running-too-slowly</link><guid isPermaLink="true">https://dbaintheshadow.com/ogg-replicat-is-running-too-slowly</guid><category><![CDATA[ogg]]></category><category><![CDATA[19c]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[replication]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Sun, 28 Sep 2025 15:50:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759058040923/9281b2c6-9609-4e38-ba5d-f1ac890b85a7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <a target="_blank" href="https://dbaenlasombra.com/ogg-lentitud-de-replicat"><em>Spanish version</em></a><em>.</em></p>
<p>Today, let’s look at a case where the Replicat process is running too slowly.</p>
<p>The situation with OGG when they notified me was as follows:</p>
<pre><code class="lang-bash">GGSCI 1&gt; info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING
EXTRACT     RUNNING     EXXX        00:00:06      00:00:09
REPLICAT    RUNNING     Rxxx        53:14:49      00:00:03
</code></pre>
<p>The Replicat process <strong>RXXX</strong> had a lag from the beginning that kept growing and never decreased, how come?</p>
<p>As a small note, OGG is running on version 19.1.0.0.4.</p>
<p>First, let’s check the processing statistics in minutes:</p>
<pre><code class="lang-bash">GGSCI 4&gt; stats replicat Rxxx, totalsonly *.*, reportrate min

Sending STATS request to REPLICAT Rxxx...

Start of Statistics at 2025-09-28 00:23:05.

DDL replication statistics:

*** Total statistics since replicat started     ***
        Opees rations                                       104.00
        Mapped operations                                  0.00
        Unmapped operations                              104.00
        Other operations                                   0.00
        Excluded operations                                0.00
        Errors                                             0.00
        Retried errors                                     0.00
        Discarded errors                                   0.00
        Ignored errors                                     0.00

Cumulative totals <span class="hljs-keyword">for</span> specified table(s):

*** Total statistics since 2025-09-27 23:19:02 ***
        Total inserts/minute                       0.00
        Total updates/minute                       0.00
        Total deletes/minute                       0.00
        Total upserts/minute                       0.00
        Total discards/minute                  13497.48
        Total operations/minute                    0.00

*** Daily statistics since 2025-09-28 00:00:00 ***

        No database operations have been performed.

*** Hourly statistics since 2025-09-28 00:00:00 ***

        No database operations have been performed.

*** Latest statistics since 2025-09-27 23:19:02 ***
        Total inserts/minute                       0.00
        Total updates/minute                       0.00
        Total deletes/minute                       0.00
        Total upserts/minute                       0.00
        Total discards/minute                 864456.00
        Total operations/minute                    0.00

End of Statistics.
</code></pre>
<p>Here, we can observe performance issues, such as a lower number of operations compared to other processes, or very few DML operations.</p>
<p>Let’s review the process definition:</p>
<pre><code class="lang-bash">REPLICAT Rxxx

useridalias ogg_xxxx
assumetargetdefs

DDL INCLUDE ALL
DDLERROR DEFAULT IGNORE

discardfile ./dirrpt/Rxxx.dsc, Append,megabytes 4000
REPERROR (0001,discard)
REPERROR (1403,discard)

TABLE SCHEMA.TABLE , TARGET PDB.SCHEMA.TABLE;
</code></pre>
<p>Here, we can see several points. On one hand, the source is a <strong><em>single instance</em></strong>, while the target is <strong><em>multitenant</em></strong>. On the other hand, I didn’t see the <strong>HANDLECOLLISIONS</strong> parameter in the definition.</p>
<p>The <strong>HANDLECOLLISIONS</strong> parameter, it’s very useful in order to iron out the conflicts when the replicat is running. These conflicts are known as <strong>collisions</strong>.</p>
<p>This parameter helps OGG manage collisions efficiently, such as:</p>
<ul>
<li><p><strong>Insert</strong>: OGG tries to insert a row when that already exists in the target.</p>
</li>
<li><p><strong>Update</strong>: OGG tries to perform an update when the row doesn’t exists in the target.</p>
</li>
<li><p><strong>Delete</strong>: OGG tries to remove a row when the row doesn’t exists in the target.</p>
</li>
</ul>
<p>Alright, enough talking theory! Let’s get our hands dirty!</p>
<p>We modified the process in order to include the parameter. You can see it below:</p>
<pre><code class="lang-bash">REPLICAT Rxxx

useridalias ogg_xxxx
assumetargetdefs

DDL INCLUDE ALL
DDLERROR DEFAULT IGNORE
HANDLECOLLISIONS

discardfile ./dirrpt/Rxxx.dsc, Append,megabytes 4000
REPERROR (0001,discard)
REPERROR (1403,discard)

TABLE SCHEMA.TABLE , TARGET PDB.SCHEMA.TABLE;
</code></pre>
<p>After running the process again, I waited a few hours in order to observe the results.</p>
<p>As you can see below, the process is working better than before.</p>
<pre><code class="lang-bash">GGSCI 1&gt; info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING
EXTRACT     RUNNING     EXXX        00:00:02      00:00:07
REPLICAT    RUNNING     Rxxx        26:38:41      00:00:00
</code></pre>
<p>Let’s check the processing statistics again:</p>
<pre><code class="lang-bash">GGSCI 3&gt;   stats replicat Rxxx, totalsonly *.*, reportrate min

Sending STATS request to REPLICAT Rxxx...

Start of Statistics at 2025-09-28 12:19:43.

DDL replication statistics:

*** Total statistics since replicat started     ***
        Operations                                      4804.00
        Mapped operations                                  5.00
        Unmapped operations                             4799.00
        Other operations                                   0.00
        Excluded operations                                0.00
        Errors                                             7.00
        Retried errors                                     0.00
        Discarded errors                                   0.00
        Ignored errors                                     6.00

Cumulative totals <span class="hljs-keyword">for</span> specified table(s):

*** Total statistics since 2025-09-28 00:26:27 ***
        Total inserts/minute                   63670.08
        Total updates/minute                       0.00
        Total deletes/minute                   54358.40
        Total upserts/minute                       0.00
        Total discards/minute                      0.00
        Total operations/minute               118028.47
        Total insert collisions/minute         63670.08
        Total delete collisions/minute         31318.92

*** Daily statistics since 2025-09-28 00:26:27 ***
        Total inserts/minute                   63670.08
        Total updates/minute                       0.00
        Total deletes/minute                   54358.40
        Total upserts/minute                       0.00
        Total discards/minute                      0.00
        Total operations/minute               118028.47
        Total insert collisions/minute         63670.08
        Total delete collisions/minute         31318.92

*** Hourly statistics since 2025-09-28 12:00:00 ***
        Total inserts/minute                    7272.71
        Total updates/minute                       0.00
        Total deletes/minute                  421092.52
        Total upserts/minute                       0.00
        Total discards/minute                      0.00
        Total operations/minute               428365.24
        Total insert collisions/minute          7272.71
        Total delete collisions/minute        421092.52

*** Latest statistics since 2025-09-28 00:26:27 ***
        Total inserts/minute                45413289.00
        Total updates/minute                       0.00
        Total deletes/minute                38771646.00
        Total upserts/minute                       0.00
        Total discards/minute                      0.00
        Total operations/minute             84184935.00
        Total insert collisions/minute      45413289.00
        Total delete collisions/minute      22338520.00

End of Statistics.
</code></pre>
<p>Here, we can observe several points:</p>
<ul>
<li><p>The number of operations has exceeded 4000 instead of 104.</p>
</li>
<li><p>The dml workflow is working properly.</p>
</li>
</ul>
<p>The performance issue has been worked out.</p>
<p><img src="https://media1.giphy.com/media/v1.Y2lkPWZjZGU1NDk1aGI3OWphNTlja215bmxxa3N1MTlvMzUzeDdmZjl5cDlpYWxmNmRoZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/UqvkuqTLBP8mfDgbEI/giphy.gif" alt="Caso Cerrado Telemundo GIF by Universo (imagen GIF)" /></p>
<p>I hope you enjoyed reading this post :)</p>
]]></content:encoded></item><item><title><![CDATA[[23ai] Installing Oracle23ai on OraLinux9]]></title><description><![CDATA[If you prefer to read in Spanish Spanish version.
The goal of this post is as follows: To create a new database using the Oracle Database Configuration Assistant (DBCA) on 23ai.
In this case, we defined an IaaS with Oracle Linux 9 on OCI. So, first t...]]></description><link>https://dbaintheshadow.com/23ai-installing-oracle23ai-on-oralinux9</link><guid isPermaLink="true">https://dbaintheshadow.com/23ai-installing-oracle23ai-on-oralinux9</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle 23ai]]></category><category><![CDATA[ACE]]></category><dc:creator><![CDATA[David Sanz]]></dc:creator><pubDate>Fri, 05 Sep 2025 09:22:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755859016985/9cf8e5ef-ac9b-4ff4-9416-4084974f7c96.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you prefer to read in Spanish</em> <em>Spanish version.</em></p>
<p>The goal of this post is as follows: To create a new database using the <em>Oracle Database Configuration Assistant</em> (<strong>DBCA</strong>) on 23ai.</p>
<p>In this case, we defined an <strong>IaaS</strong> with <strong>Oracle Linux 9</strong> on OCI. So, first thing first, we need to set up an Oracle 23ai because it is a new environment.</p>
<pre><code class="lang-bash">[root@~]<span class="hljs-comment"># grep PRETTY_NAME /etc/os-release</span>
PRETTY_NAME=<span class="hljs-string">"Oracle Linux Server 9.6"</span>
</code></pre>
<p>In order to successfully set up Oracle 23ai, we need the following files:</p>
<pre><code class="lang-bash">[root@test1 tmp]<span class="hljs-comment"># ls -lac *rpm</span>
-rw-r--r--. 1 root root 1412957372 Sep  2 09:47 oracle-database-free-23ai-23.9-1.el9.x86_64.rpm
-rw-r--r--. 1 root root      30688 Sep  2 09:30 oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm
</code></pre>
<p>A quick note on where we can find these files:</p>
<ul>
<li><p>oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm <a target="_blank" href="https://yum.oracle.com/repo/OracleLinux/OL8/developer/x86_64/">here</a>.</p>
</li>
<li><p>oracle-database-free-23ai-23.9-1.el9.x86_64.rpm. <a target="_blank" href="https://www.oracle.com/database/free/get-started/">here</a>.</p>
</li>
</ul>
<p>So, let's get down to business!</p>
<h3 id="heading-installing-and-configuring">Installing and Configuring</h3>
<ul>
<li>Install the Linux RPM oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm:</li>
</ul>
<pre><code class="lang-bash">[root@tmp]<span class="hljs-comment"># dnf install oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm -y</span>
Last metadata expiration check: 1:54:40 ago on Tue 02 Sep 2025 07:46:07 AM GMT.
Dependencies resolved.
....
....
Complete!
</code></pre>
<ul>
<li>Install the Linux RPM oracle-database-free-23ai-23.9-1.el9.x86_64.rpm:</li>
</ul>
<pre><code class="lang-bash">[root@test1 tmp]<span class="hljs-comment"># wget https://objectstorage.....</span>
[root@test1 tmp]<span class="hljs-comment"># dnf install oracle-database-free-23ai-23.9-1.el9.x86_64.rpm -y</span>
Last metadata expiration check: 2:06:18 ago on Tue 02 Sep 2025 07:46:07 AM GMT.
Dependencies resolved.
....
....  
 3/3
Installed:
  oracle-database-free-23ai-23.9-1.x86_64  oracle-database-preinstall-23ai-1.0-3.el9.x86_64
Complete!
</code></pre>
<p>So, after running both rpm, we can find the following script, <strong>oracle-free-23ai,</strong> in /etc/init.d in order to create the database 23ai. Before running it the script, we need to set the DB_PASSWORD environment variable.</p>
<pre><code class="lang-bash">[root@test1 tmp]<span class="hljs-comment">#  export DB_PASSWORD=oracle</span>
[root@test1 tmp]<span class="hljs-comment"># (echo "${DB_PASSWORD}"; echo "${DB_PASSWORD}";) | /etc/init.d/oracle-free-23ai configure</span>
Specify a password to be used <span class="hljs-keyword">for</span> database accounts. Oracle recommends that the password entered should be at least 8 characters <span class="hljs-keyword">in</span> length, contain at least 1 uppercase character, 1 lower <span class="hljs-keyword">case</span> character and 1 digit [0-9]. Note that the same password will be used <span class="hljs-keyword">for</span> SYS, SYSTEM and PDBADMIN accounts:
Confirm the password:
Configuring Oracle Listener.
Listener configuration succeeded.
Configuring Oracle Database FREE.
Enter SYS user password:
*****
Enter SYSTEM user password:
********
Enter PDBADMIN User Password:
*********
Prepare <span class="hljs-keyword">for</span> db operation
7% complete
Copying database files
29% complete
Creating and starting Oracle instance
30% complete
33% complete
36% complete
39% complete
43% complete
Completing Database Creation
47% complete
49% complete
50% complete
Creating Pluggable Databases
54% complete
71% complete
Executing Post Configuration Actions
93% complete
Running Custom Scripts
100% complete
Database creation complete. For details check the logfiles at:
 /opt/oracle/cfgtoollogs/dbca/FREE.
Database Information:
Global Database Name:FREE
System Identifier(SID):FREE
Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/FREE/FREE.log"</span> <span class="hljs-keyword">for</span> further details.

Connect to Oracle Database using one of the connect strings:
     Pluggable database: test1/FREEPDB1
     Multitenant container database: test1
</code></pre>
<p>Done! In this setup, we can already with 23ai in our environment. Lastly,as a wee bit trick, we can to configure <strong>.bashrc</strong> and <strong>.bash_profile</strong> files in order to work with the binaries easily, such as <strong>sqlplus</strong>, <strong>dbca</strong>, or even <strong>tkproff</strong>.</p>
<p>Below we can see the <strong>.bashrc</strong> after updating it:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># .bashrc</span>
<span class="hljs-comment"># Source global definitions</span>
<span class="hljs-keyword">if</span> [ -f /etc/bashrc ]; <span class="hljs-keyword">then</span>
        . /etc/bashrc
<span class="hljs-keyword">fi</span>
<span class="hljs-comment"># User specific environment</span>
<span class="hljs-keyword">if</span> ! [[ <span class="hljs-string">"<span class="hljs-variable">$PATH</span>"</span> =~ <span class="hljs-string">"<span class="hljs-variable">$HOME</span>/.local/bin:<span class="hljs-variable">$HOME</span>/bin:"</span> ]]
<span class="hljs-keyword">then</span>
    PATH=<span class="hljs-string">"<span class="hljs-variable">$HOME</span>/.local/bin:<span class="hljs-variable">$HOME</span>/bin:<span class="hljs-variable">$PATH</span>"</span>
<span class="hljs-keyword">fi</span>
<span class="hljs-built_in">export</span> PATH
<span class="hljs-comment"># Uncomment the following line if you don't like systemctl's auto-paging feature:</span>
<span class="hljs-comment"># export SYSTEMD_PAGER=</span>
<span class="hljs-comment"># User specific aliases and functions</span>
<span class="hljs-keyword">if</span> [ -d ~/.bashrc.d ]; <span class="hljs-keyword">then</span>
        <span class="hljs-keyword">for</span> rc <span class="hljs-keyword">in</span> ~/.bashrc.d/*; <span class="hljs-keyword">do</span>
                <span class="hljs-keyword">if</span> [ -f <span class="hljs-string">"<span class="hljs-variable">$rc</span>"</span> ]; <span class="hljs-keyword">then</span>
                        . <span class="hljs-string">"<span class="hljs-variable">$rc</span>"</span>
                <span class="hljs-keyword">fi</span>
        <span class="hljs-keyword">done</span>
<span class="hljs-keyword">fi</span>
ORACLE_HOME=/opt/oracle/product/23ai/dbhomeFree; <span class="hljs-built_in">export</span> ORACLE_HOME
PATH=/bin:/usr/bin:/usr/<span class="hljs-built_in">local</span>/sbin:/usr/sbin:<span class="hljs-variable">$ORACLE_HOME</span>/bin:<span class="hljs-variable">$ORACLE_HOME</span>/lib:<span class="hljs-variable">$ORACLE_HOME</span>/OPatch/:<span class="hljs-variable">$ORACLE_HOME</span>/lib; <span class="hljs-built_in">export</span> PATH
LD_LIBRARY_PATH=<span class="hljs-variable">${ORACLE_HOME}</span>/lib; <span class="hljs-built_in">export</span> LD_LIBRARY_PATH

ORACLE_SID=FREE; <span class="hljs-built_in">export</span> ORACLE_SID
PDB_NAME=FREEPDB1; <span class="hljs-built_in">export</span> PDB_NAME
</code></pre>
<p>Don’t forget that the goal is to use <strong>dbca</strong> in order to do the following:</p>
<ul>
<li><p>Generate a template using the current database.</p>
</li>
<li><p>Drop the current database.</p>
</li>
<li><p>Create a new database using the response and template files.</p>
</li>
</ul>
<p>We run <strong>dbca</strong> with the option -<strong>silent</strong>. The <strong>-silent</strong> option indicates to run <strong>dbca</strong> in silent mode.</p>
<h3 id="heading-generate-a-template">Generate a template</h3>
<pre><code class="lang-bash">[oracle@test1 ~]$ dbca -silent \
-createTemplateFromDB \
-sourceDB FREE \
-templateName FREE.template \
-sysDBAUserName SYS \
-sysDBAPassword oracle
Prepare <span class="hljs-keyword">for</span> db operation
33% complete
Creating a template from the database
37% complete
40% complete
43% complete
47% complete
50% complete
53% complete
57% complete
60% complete
63% complete
67% complete
Creating template
100% complete
The template <span class="hljs-string">"/opt/oracle/product/23ai/dbhomeFree/assistants/dbca/templates/FREE.template.dbt"</span> creation completed.
Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/silent.log_2025-09-02_12-09-54PM_170638"</span> <span class="hljs-keyword">for</span> further details.
</code></pre>
<h3 id="heading-drop-the-current-database">Drop the current database</h3>
<p>Before dropping the database, we need to switch off the database.</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ dbca -silent \
-deleteDatabase \
-sourceDB FREE \
-sysDBAUserName sys \
-sysDBAPassword oracle
[WARNING] [DBT-11503] The instance (FREE) is not running on the <span class="hljs-built_in">local</span> node. This may result <span class="hljs-keyword">in</span> partial delete of Oracle database.
   CAUSE: A locally running instance is required <span class="hljs-keyword">for</span> complete deletion of Oracle database instance and database files.
   ACTION: Specify a locally running database, or execute DBCA on a node <span class="hljs-built_in">where</span> the database instance is running.
[WARNING] [DBT-19202] The Database Configuration Assistant will delete the Oracle instances and datafiles <span class="hljs-keyword">for</span> your database. All information <span class="hljs-keyword">in</span> the database will be destroyed.
Prepare <span class="hljs-keyword">for</span> db operation
32% complete
Connecting to database
35% complete
39% complete
42% complete
45% complete
48% complete
52% complete
65% complete
Updating network configuration files
68% complete
Deleting instance and datafiles
84% complete
100% complete
Database deletion completed.
Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/FREE/FREE0.log"</span> <span class="hljs-keyword">for</span> further details.
</code></pre>
<h3 id="heading-create-a-new-database">Create a new database</h3>
<p>To create the database, we are going to work with the following files:</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ ls -lac config/
total 52
drwxr-xr-x. 2 oracle oinstall    49 Sep  3 06:35 .
drwx------. 3 oracle oinstall   127 Sep  2 15:47 ..
-rw-r-----. 1 oracle oinstall 20942 Sep  2 15:47 FREE.template.dbt
-rw-r-----. 1 oracle oinstall 25378 Sep  3 06:35 shadow.rsp
</code></pre>
<ul>
<li><strong>FREE.template.dbt</strong>, it is the template that we created in the previous step. Therefore, we are going to edit the template in order to remove the references to FREEPDB1. The goal is to create the cdb without pdbs</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756818902278/4902b0c3-df86-4a22-b5ca-240319b3a2b1.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>shadow.rsp</strong>. It is the response file that we use to run <strong>dbca</strong>. It is a copy of response file template (<em>$ORACLE_HOME/assistants/dbca/dbca.rsp</em>) tailored to our needs.</p>
<p>  Below, you can see the response file after it has been upgraded:</p>
<pre><code class="lang-bash">  [oracle@test1 ~]$ more config/shadow.rsp | grep -v ^$ | grep -v ^<span class="hljs-comment">#</span>
  responseFileVersion=/oracle/assistants/rspfmt_dbca_response_schema_v23.0.0
  gdbName=FREE
  sid=FREE
  createAsContainerDatabase=<span class="hljs-literal">true</span>
  numberOfPDBs=0
  templateName=/home/oracle/config/FREE.template.dbt
  sysPassword=*********
  systemPassword=********
</code></pre>
</li>
</ul>
<p>After we have upgraded both files, we run <strong>dbca</strong> in silent mode using our response file :</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ dbca -createDatabase -silent -responseFile /home/oracle/config/shadow.rsp
Prepare <span class="hljs-keyword">for</span> db operation
4% complete
Creating and starting Oracle instance
5% complete
6% complete
8% complete
Creating database files
12% complete
Creating data dictionary views
13% complete
16% complete
17% complete
18% complete
24% complete
Oracle JVM
30% complete
36% complete
42% complete
44% complete
Oracle Text
46% complete
48% complete
Oracle OLAP
52% complete
Oracle Spatial
53% complete
60% complete
Oracle Label Security
68% complete
Oracle Database Vault
76% complete
Creating cluster database views
77% complete
84% complete
Completing Database Creation
86% complete
88% complete
Executing Post Configuration Actions
100% complete
Database creation complete. For details check the logfiles at:
 /opt/oracle/cfgtoollogs/dbca/FREE.
Database Information:
Global Database Name:FREE
System Identifier(SID):FREE
Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/FREE/FREE10.log"</span> <span class="hljs-keyword">for</span> further details
</code></pre>
<p>Connect to the database as the SYS user:</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ sqlplus /nolog

SQL*Plus: Release 23.0.0.0.0 - Production on Wed Sep 3 09:57:09 2025
Version 23.9.0.25.07

Copyright (c) 1982, 2025, Oracle.  All rights reserved.

SQL&gt;
SQL&gt; conn / as sysdba
Connected.
SQL&gt; show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB<span class="hljs-variable">$SEED</span>                       READ ONLY  NO
</code></pre>
<p>Up to now, The database is up without pdbs, only the seed, thus we have configurated in our template.</p>
<p>We are going to make another test with the parameter <strong>numberOfPDBs</strong>. The functionality of the parameter is as follows: <em>Number of PDBs to create. The default is zero</em>. So If we look inside the response file that we have used, we can see that we had defined the variable with value zero.</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ grep numberOfPDBs  config/shadow.rsp
<span class="hljs-comment"># Name          : numberOfPDBs</span>
numberOfPDBs=0
</code></pre>
<p>Hold on!,If we use the original template with the response file, Will it create a PDB or not? If we remenber, the original template had one PDB</p>
<p>Let’s check it!</p>
<ul>
<li><p>Drop the current database:</p>
<pre><code class="lang-bash">  [oracle@test1 ~]$ dbca -silent \
  -deleteDatabase \
  -sourceDB FREE \
  -sysDBAUserName sys \
  -sysDBAPassword ******
  [WARNING] [DBT-11503] The instance (FREE) is not running on the <span class="hljs-built_in">local</span> node. This may result <span class="hljs-keyword">in</span> partial delete of Oracle database.
     CAUSE: A locally running instance is required <span class="hljs-keyword">for</span> complete deletion of Oracle database instance and database files.
     ACTION: Specify a locally running database, or execute DBCA on a node <span class="hljs-built_in">where</span> the database instance is running.
  [WARNING] [DBT-19202] The Database Configuration Assistant will delete the Oracle instances and datafiles <span class="hljs-keyword">for</span> your database. All information <span class="hljs-keyword">in</span> the database will be destroyed.
  Prepare <span class="hljs-keyword">for</span> db operation
  32% complete
  Connecting to database
  35% complete
  39% complete
  42% complete
  45% complete
  48% complete
  52% complete
  65% complete
  Updating network configuration files
  68% complete
  Deleting instance and datafiles
  84% complete
  100% complete
  Database deletion completed.
  Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/FREE/FREE11.log"</span> <span class="hljs-keyword">for</span> further details.
</code></pre>
</li>
<li><p>Create the database:</p>
<pre><code class="lang-bash">  [oracle@test1 ~]$ dbca -createDatabase -silent -responseFile /home/oracle/config/shadow.rsp
  Enter PDBADMIN User Password:

  Prepare <span class="hljs-keyword">for</span> db operation
  4% complete
  Creating and starting Oracle instance
  5% complete
  6% complete
  8% complete
  Creating database files
  12% complete
  Creating data dictionary views
  13% complete
  16% complete
  17% complete
  18% complete
  24% complete
  Oracle JVM
  30% complete
  36% complete
  42% complete
  44% complete
  Oracle Text
  46% complete
  48% complete
  Oracle OLAP
  52% complete
  Oracle Spatial
  53% complete
  60% complete
  Oracle Label Security
  68% complete
  Oracle Database Vault
  76% complete
  Creating cluster database views
  77% complete
  84% complete
  Completing Database Creation
  86% complete
  88% complete
  Executing Post Configuration Actions
  100% complete
  Database creation complete. For details check the logfiles at:
   /opt/oracle/cfgtoollogs/dbca/FREE.
  Database Information:
  Global Database Name:FREE
  System Identifier(SID):FREE
  Look at the <span class="hljs-built_in">log</span> file <span class="hljs-string">"/opt/oracle/cfgtoollogs/dbca/FREE/FREE13.log"</span> <span class="hljs-keyword">for</span> further details.
</code></pre>
</li>
</ul>
<p>Connect to the database as the SYS user:</p>
<pre><code class="lang-bash">[oracle@test1 ~]$ sqlplus /nolog

SQL*Plus: Release 23.0.0.0.0 - Production on Wed Sep 3 12:02:06 2025
Version 23.9.0.25.07

Copyright (c) 1982, 2025, Oracle.  All rights reserved.

SQL&gt; conn / as sysdba
Connected.
SQL&gt; show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB<span class="hljs-variable">$SEED</span>                       READ ONLY  NO
SQL&gt;! grep pdb_dbid /home/oracle/config/FREE.template.dbt
      &lt;PluggableDatabase pdb_name=<span class="hljs-string">"PDB<span class="hljs-variable">$SEED</span>"</span> con_id=<span class="hljs-string">"2"</span> pdb_dbid=<span class="hljs-string">"3172087764"</span>/&gt;
      &lt;PluggableDatabase pdb_name=<span class="hljs-string">"FREEPDB1"</span> con_id=<span class="hljs-string">"3"</span> pdb_dbid=<span class="hljs-string">"302716810"</span>/&gt;
</code></pre>
<p>We can see that we don’t have any PDBs, only the seed.</p>
<p>Although our template has the definition of PDB "FREEPDB1", the response file indicates to <strong>dbca</strong> that number of PDBs is zero (numberOfPDBs=0).</p>
<p>If you want, you can download the files that I used from <a target="_blank" href="https://github.com/dbaenlasombra/dbca">here</a>.</p>
<p>I hope you enjoyed reading this post :)</p>
]]></content:encoded></item></channel></rss>