{
  "schema_version": 2,
  "id": "integrate/redis-data-integration/data-pipelines/prepare-dbs/oracle",
  "title": "Prepare Oracle and Oracle RAC for RDI",
  "url": "https://redis.io/docs/latest/integrate/redis-data-integration/1.19.1/data-pipelines/prepare-dbs/oracle/",
  "summary": "Prepare Oracle and Oracle RAC databases to work with RDI",
  "content": "\nOracle provides two main systems that Debezium can use to capture data changes:\n\n- [LogMiner](#logminer)\n- [XStream](#xstream)\n\nThe sections below explain how to configure each system for use with Debezium and RDI.\nThe checklists summarize the steps you should follow to configure each system.\nYou may find it helpful to use them to track your progress as you work through the steps.\n\n**LogMiner**\n\n```checklist {id=\"oraclelogminerlist\"}\n- [ ] [Configure Oracle LogMiner](#1-configure-oracle-logminer)\n- [ ] [Enable supplemental logging](#supp-logging)\n- [ ] [Check the redo log sizing](#3-check-the-redo-log-sizing)\n- [ ] [Set the Archive log destination](#4-set-the-archive-log-destination)\n- [ ] [Create a user for the connector](#create-dbz-user)\n```\n\n**XStream**\n\n```checklist {id=\"oraclexstreamlist\"}\n- [ ] [Configure recovery area](#1-configure-recovery-area)\n- [ ] [Enable GoldenGate replication](#2-enable-goldengate-replication)\n- [ ] [Configure XStream](#3-configure-xstream)\n- [ ] [Enable supplemental logging](#4-enable-supplemental-logging)\n- [ ] [Create XStream users](#5-create-xstream-users)\n- [ ] [Create an XStream outbound server](#6-create-an-xstream-outbound-server)\n- [ ] [Add a custom Docker image for the Debezium server](#7-add-a-custom-docker-image-for-the-debezium-server)\n- [ ] [Make RDI use the custom image](#8-make-rdi-use-the-custom-image-vm-installation)\n- [ ] [Enable the Oracle configuration in RDI](#9-enable-the-oracle-configuration-in-rdi)\n```\n\n**Optional: XMLTYPE Support**\n\n```checklist {id=\"oraclexmltypelist\"}\n- [ ] [Create a custom Debezium Server image](#create-a-custom-debezium-server-image)\n- [ ] [Configure RDI for XMLTYPE support](#configure-rdi-for-xmltype-support)\n- [ ] [Test XMLTYPE support](#test-xmltype-support)\n```\n\n## LogMiner\n\nFollow the steps below to configure\n[LogMiner](https://docs.oracle.com/en/database/oracle/oracle-database/19/sutil/oracle-logminer-utility.html)\nand prepare your database for use with RDI.\n\n### 1. Configure Oracle LogMiner\n\nThe following example shows the configuration for Oracle LogMiner.\n\n\u003e [!NOTE]\n\u003e [Amazon RDS for Oracle](https://aws.amazon.com/rds/oracle/)\n\u003e doesn't let you execute the commands\n\u003e in the example below or let you log in as `sysdba`. See the\n\u003e separate example below to [configure Amazon RDS for Oracle](#config-aws).\n\n```sql\nORACLE_SID=ORACLCDB dbz_oracle sqlplus /nolog\n\nCONNECT sys/top_secret AS SYSDBA\nalter system set db_recovery_file_dest_size = 10G;\nalter system set db_recovery_file_dest = '/opt/oracle/oradata/recovery_area' scope=spfile;\n-- ======================================================================================================================================================\n-- !!!IMPORTANT!!!: \n-- In order to avoid Oracle downtime, please check if the LOG_MODE on your database is already set to `ARCHIVELOG` before executing the following commands: \n-- SELECT log_mode FROM v$database;\n-- If the LOG_MODE is already `ARCHIVELOG`, then you can skip the rest of the commands in this script\n-- ======================================================================================================================================================\nshutdown immediate\nstartup mount\nalter database archivelog;\nalter database open;\n-- You should now see \"Database log mode: Archive Mode\"\narchive log list\n\nexit;\n```\n\n#### Configure Amazon RDS for Oracle {#config-aws}\n\nAWS provides its own set of commands to configure LogMiner.\n\n\u003e [!NOTE]\n\u003e Before executing these commands,\n\u003e you must enable backups on your Oracle AWS RDS instance.\n\nCheck that Oracle has backups enabled with the following command:\n\n```sql\nSQL\u003e SELECT LOG_MODE FROM V$DATABASE;\n\nLOG_MODE\n------------\nARCHIVELOG\n```\n\nThe `LOG_MODE` should be set to `ARCHIVELOG`. If it isn't then you\nshould reboot your Oracle AWS RDS instance.\n\nOnce `LOG_MODE` is correctly set to ARCHIVELOG, execute the following\ncommands to complete the LogMiner configuration. The first command enables\narchive logging and the second adds [supplemental logging](#supp-logging).\n\n```sql\nexec rdsadmin.rdsadmin_util.set_configuration('archivelog retention hours',24);\nexec rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD');\n```\n\n### 2. Enable supplemental logging {#supp-logging}\n\nYou must enable supplemental logging for the tables you want to capture or\nfor the entire database. This lets Debezium capture the state of\ndatabase rows before and after changes occur. \n\nThe following example shows how to configure supplemental logging for all columns\nin a single table called `inventory.customers`:\n\n```sql\nALTER TABLE inventory.customers ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\n```\n\n\u003e [!NOTE]\n\u003e If you enable supplemental logging for *all* table columns, you will\n\u003e probably see the size of the Oracle redo logs increase dramatically. Avoid this\n\u003e by using supplemental logging only when you need it.  \n\nYou must also enable minimal supplemental logging at the database level with\nthe following command:\n\n```sql\nALTER DATABASE ADD SUPPLEMENTAL LOG DATA;\n```\n\n### 3. Check the redo log sizing\n\nBefore you use the Debezium connector, you should check with your\ndatabase administrator that there are enough\nredo logs with enough capacity to store the data dictionary for your\ndatabase. In general, the size of the data dictionary increases with the number\nof tables and columns in the database. If you don't have enough capacity in\nthe logs then you might see performance problems with both the database and\nthe Debezium connector.\n\n### 4. Set the Archive log destination\n\nYou can configure up to 31 different destinations for archive logs\n(you must have administrator privileges to do this). You can set parameters for\neach destination to specify its purpose, such as log shipping for physical\nstandbys, or external storage to allow for extended log retention. Oracle reports\ndetails about archive log destinations in the `V$ARCHIVE_DEST_STATUS` view.\n\nThe Debezium Oracle connector only uses destinations that have a status of\n`VALID` and a type of `LOCAL`. If you only have one destination with these\nsettings then Debezium will use it automatically.\nIf you have more than one destination with these settings,\nthen you should consult your database administrator about which one to\nchoose for Debezium.\n\nUse the `log.mining.archive.destination.name` property in the connector configuration\nto select the archive log destination for Debezium.\n\nFor example, suppose you have two archive destinations, `LOG_ARCHIVE_DEST_2` and\n`LOG_ARCHIVE_DEST_3`, and they both have status set to `VALID` and type set to\n`LOCAL`. Debezium could use either of these destinations, so you must select one\nof them explicitly in the configuration. To select `LOG_ARCHIVE_DEST_3`, you would\nuse the following setting:\n\n```json\n{\n    \"log.mining.archive.destination.name\": \"LOG_ARCHIVE_DEST_3\"\n}\n```\n\n### 5. Create a user for the connector {#create-dbz-user}\n\nThe Debezium Oracle connector must run as an Oracle LogMiner user with specific permissions.\n\nTypically, when you create the Oracle account for the connector, \nyou grant the account a level of access that permits the connector to detect changes from all tables in the database. \nHowever, in some environments, security policies might prohibit you from granting such a broad level of access.\n\nThe following example shows some SQL that creates an Oracle user account for the connector in a multi-tenant database model. \nThe grant settings in the example permit the Debezium user to access all user tables in the database.\n\nTo comply with security policies, you can modify the `SELECT ANY TABLE` and `FLASHBACK ANY TABLE` grants \nso that the connector can access only those tables that you intend to capture.\n\nDo not modify other grants, such as the `SELECT ANY TRANSACTION` grant, \nor the set of `SELECT ON V_$` grants, which provide access to dynamic performance views (`V_$`). \nThese grants are required for the connector to function.\n\n\u003e [!NOTE]\n\u003e To prevent data loss, if you restrict the scope of the SELECT and FLASHBACK grants, \n\u003e be sure that the modified scope is compatible with the settings in the connector’s include configuration. \n\u003e The privileges that you set for the account must permit reading from all of the tables that you want the connector to capture.\n\n\u003e [!NOTE]\n\u003e This example uses `ORCLCDB` as the container database (CDB) name and `ORCLPDB1` as the pluggable database (PDB) name. Replace these with the CDB and PDB names from your own environment.\n\n```sql\nsqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba\nCREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/logminer_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\nexit;\n\nsqlplus sys/top_secret@//localhost:1521/ORCLPDB1 as sysdba\nCREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/logminer_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\nexit;\n\nsqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba\n\nCREATE USER c##dbzuser IDENTIFIED BY dbz\n    DEFAULT TABLESPACE logminer_tbs\n    QUOTA UNLIMITED ON logminer_tbs\n    CONTAINER=ALL;\n\nGRANT CREATE SESSION TO c##dbzuser CONTAINER=ALL;\nGRANT SET CONTAINER TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$DATABASE to c##dbzuser CONTAINER=ALL;\n\n-- See `Limiting privileges` below if the privileges\n-- granted by these two commands raise security concerns.\nGRANT FLASHBACK ANY TABLE TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ANY TABLE TO c##dbzuser CONTAINER=ALL;\n-- \n\nGRANT SELECT_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL;\nGRANT EXECUTE_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ANY TRANSACTION TO c##dbzuser CONTAINER=ALL;\nGRANT LOGMINING TO c##dbzuser CONTAINER=ALL;\n\n-- See `Limiting privileges` below if the privileges\n-- granted by these two commands raise security concerns.\nGRANT CREATE TABLE TO c##dbzuser CONTAINER=ALL;\nGRANT LOCK ANY TABLE TO c##dbzuser CONTAINER=ALL;\n-- \n\nGRANT CREATE SEQUENCE TO c##dbzuser CONTAINER=ALL;\n\nGRANT EXECUTE ON DBMS_LOGMNR TO c##dbzuser CONTAINER=ALL;\nGRANT EXECUTE ON DBMS_LOGMNR_D TO c##dbzuser CONTAINER=ALL;\n\nGRANT SELECT ON V_$LOG TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$LOG_HISTORY TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$LOGMNR_LOGS TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$LOGMNR_CONTENTS TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$LOGMNR_PARAMETERS TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$LOGFILE TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$ARCHIVED_LOG TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$ARCHIVE_DEST_STATUS TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$TRANSACTION TO c##dbzuser CONTAINER=ALL;\n\nGRANT SELECT ON V_$MYSTAT TO c##dbzuser CONTAINER=ALL;\nGRANT SELECT ON V_$STATNAME TO c##dbzuser CONTAINER=ALL;\n\nexit;\n```\n\n| Role name                | Description                                                                                                                                                                                                                                                                                                                                                                                            |\n|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| CREATE SESSION           | Enables the connector to connect to Oracle.                                                                                                                                                                                                                                                                                                                                                            |\n| SET CONTAINER            | Enables the connector to switch between pluggable databases. This is only required when the Oracle installation has container database support (CDB) enabled.                                                                                                                                                                                                                                          |\n| SELECT ON V_$DATABASE    | Enables the connector to read the V_$DATABASE table.                                                                                                                                                                                                                                                                                                                                                    |\n| FLASHBACK ANY TABLE      | Enables the connector to perform Flashback queries, which is how the connector performs the initial snapshot of data. Optionally, rather than granting FLASHBACK permission on all tables, you can grant the FLASHBACK privilege for specific tables only.                                                                                                                                             |\n| SELECT ANY TABLE         | Enables the connector to read any table. Optionally, rather than granting SELECT permission on all tables, you can grant the SELECT privilege for specific tables only.                                                                                                                                                                                                                                |\n| SELECT_CATALOG_ROLE      | Enables the connector to read the data dictionary, which is needed by Oracle LogMiner sessions.                                                                                                                                                                                                                                                                                                        |\n| EXECUTE_CATALOG_ROLE     | Enables the connector to write the data dictionary into the Oracle redo logs, which is needed to track schema changes.                                                                                                                                                                                                                                                                                 |\n| SELECT ANY TRANSACTION   | Enables the snapshot process to perform a Flashback snapshot query against any transaction so that the connector can read past changes from LogMiner. When FLASHBACK ANY TABLE is granted, this should also be granted. This grant is optional for Oracle 19c and later. In those later releases, the connector obtains the required privileges through the EXECUTE_CATALOG_ROLE and LOGMINING grants. |\n| LOGMINING                | This role was added in newer versions of Oracle as a way to grant full access to Oracle LogMiner and its packages. On older versions of Oracle that don’t have this role, you can ignore this grant.                                                                                                                                                                                                   |\n| CREATE TABLE             | Enables the connector to create its flush table in its default tablespace. The flush table allows the connector to explicitly control flushing of the LGWR internal buffers to disk.                                                                                                                                                                                                                   |\n| LOCK ANY TABLE           | Enables the connector to lock tables during schema snapshot. If snapshot locks are explicitly disabled via configuration, this grant can be safely ignored.                                                                                                                                                                                                                                            |\n| CREATE SEQUENCE          | Enables the connector to create a sequence in its default tablespace.                                                                                                                                                                                                                                                                                                                                  |\n| EXECUTE ON DBMS_LOGMNR   | Enables the connector to run methods in the DBMS_LOGMNR package. This is required to interact with Oracle LogMiner. On newer versions of Oracle this is granted via the LOGMINING role but on older versions, this must be explicitly granted.                                                                                                                                                         |\n| EXECUTE ON DBMS_LOGMNR_D | Enables the connector to run methods in the DBMS_LOGMNR_D package. This is required to interact with Oracle LogMiner. On newer versions of Oracle this is granted via the LOGMINING role but on older versions, this must be explicitly granted.                                                                                                                                                       |\n| SELECT ON V_$…​.          | Enables the connector to read these tables. The connector must be able to read information about the Oracle redo and archive logs, and the current transaction state, to prepare the Oracle LogMiner session. Without these grants, the connector cannot operate.                                                                                                                                      |\n\n#### Limiting privileges\n\nThe privileges granted in the example above are convenient,\nbut you may prefer to restrict them further to improve security. In particular,\nyou might want to prevent the Debezium user from creating tables, or\nselecting or locking any table.\n\nThe Debezium user needs the `CREATE TABLE` privilege to create the\n`LOG_MINING_FLUSH` table when it connects for the first\ntime. After this point, it doesn't need to create any more tables,\nso you can safely revoke this privilege with the following command:\n\n```sql\nREVOKE CREATE TABLE FROM c##dbzuser container=all;\n```\n\n[The example above](#create-dbz-user) grants the `SELECT ANY TABLE` and\n`FLASHBACK ANY TABLE` privileges for convenience, but only the tables synced to RDI\nand the `V_$XXX` tables strictly need these privileges.\nYou can replace the `GRANT SELECT ANY TABLE` command with explicit\ncommands for each table. For example, you would use commands like the\nfollowing for the tables in our sample\n[`chinook`](https://github.com/Redislabs-Solution-Architects/rdi-quickstart-postgres)\ndatabase. (Note that Oracle 19c requires you to run a separate `GRANT`\ncommand for each table individually.)\n\n```sql\nGRANT SELECT ON chinook.album TO c##dbzuser;\nGRANT SELECT ON chinook.artist TO c##dbzuser;\nGRANT SELECT ON chinook.customer TO c##dbzuser;\n...\n```\n\nSimilarly, instead of `GRANT FLASHBACK ANY TABLE`, you would use the following\ncommands:\n\n```sql\nGRANT FLASHBACK ON chinook.album TO c##dbzuser;\nGRANT FLASHBACK ON chinook.artist TO c##dbzuser;\nGRANT FLASHBACK ON chinook.customer TO c##dbzuser;\n...\n```\n\nThe `LOCK` privilege is automatically granted by the `SELECT`\nprivilege, so you can omit this command if you have granted `SELECT`\non specific tables.\n\n#### Revoking existing privileges\n\nIf you initially set the Debezium user's privileges on all tables,\nbut you now want to restrict them, you can revoke the existing\nprivileges before resetting them as described in the\n[Limiting privileges](#limiting-privileges) section.\n\nUse the following commands to revoke and reset the `SELECT` privileges:\n\n```sql\nREVOKE SELECT ANY TABLE FROM c##dbzuser container=all;\nALTER SESSION SET container=orclpdb1;\n\nGRANT SELECT ON chinook.album TO c##dbzuser;\n-- ...etc\n```\n\nThe equivalent commands for `FLASHBACK` are:\n\n```sql\nREVOKE FLASHBACK ANY TABLE FROM c##dbzuser container=all;\nALTER SESSION SET container=orclpdb1;\nGRANT FLASHBACK ON chinook.album TO c##dbzuser;\n```\n\nThe `SELECT` privilege automatically includes the `LOCK`\nprivilege, so when you grant `SELECT` for specific tables\nyou should also revoke `LOCK` on all tables:\n\n```sql\nREVOKE LOCK ANY TABLE FROM c##dbzuser container=all;\n```\n\n### 6. Configuration is complete {#logminer-complete}\n\nOnce you have followed the steps above, your Oracle database is ready\nfor Debezium to use.\n\n## XStream\n\n[XStream](https://docs.oracle.com/en/database/oracle/oracle-database/19/xstrm/introduction-to-xstream.html#GUID-5939CB6C-8BA9-4594-8F96-B0453D246722)\nis a set of database components and APIs to communicate change data to and\nfrom an Oracle database. RDI specifically uses\n[XStream Out](https://docs.oracle.com/en/database/oracle/oracle-database/19/xstrm/xstream-out.html)\nto capture changes.\n\nFollow the steps in the sections below to configure XStream to work with\nDebezium and RDI.\n\n\u003e [!NOTE]\n\u003e You should run all database commands shown below as the `sysdba` user.\n\n```sql\nsqlplus sys/\u003cPASSWORD\u003e as sysdba\n```\n\n### 1. Configure recovery area\n\n**non-RAC (single-instance):**\n\nCreate a directory for the recovery area on the Oracle host (or Oracle container if you are using a containerized Oracle).\n\nFor single-instance (non-RAC) deployments on local disk, you can use:\n\n```bash\nmkdir -p /opt/oracle/oradata/recovery_area\n```\n\n  ```sql\n  ALTER SYSTEM SET db_recovery_file_dest_size = 10G; -- Adjust size as needed\n  ALTER SYSTEM SET db_recovery_file_dest = '/opt/oracle/oradata/recovery_area' SCOPE=BOTH;\n  ```\n\n**Oracle RAC (multitenant environment):**\n\nFor Oracle RAC (cluster) environments, the Fast Recovery Area (FRA) must be on **shared storage** (ASM or a shared filesystem).\n\n- **If using ASM (recommended for RAC):**\n\n  ```sql\n  ALTER SYSTEM SET db_recovery_file_dest_size = 10G; -- Adjust size as needed\n  ALTER SYSTEM SET db_recovery_file_dest = '+FRA' SCOPE=BOTH;\n  ```\n\n  Replace `+FRA` with the ASM disk group used for your FRA. No `mkdir` is required; ASM manages the storage.\n\n- **If using a shared filesystem (NFS/OCFS2/etc.):**\n\n  ```sql\n  ALTER SYSTEM SET db_recovery_file_dest_size = 10G; -- Adjust size as needed\n  ALTER SYSTEM SET db_recovery_file_dest = '/u02/oradata/recovery_area' SCOPE=BOTH;\n  ```\n\n  The path you use must:\n\n  - Be on shared storage visible from all RAC nodes\n  - Be mounted at the **same path** on all nodes\n  - Be writable by the Oracle user\n\n  Create the directory once on the shared filesystem (it will be visible from all nodes):\n\n  ```bash\n  mkdir -p /u02/oradata/recovery_area\n  chown oracle:oinstall /u02/oradata/recovery_area\n  chmod 755 /u02/oradata/recovery_area\n  ```\n\n\n\n### 2. Enable GoldenGate replication\n\nCheck if `enable_goldengate_replication` is already set to `true`:\n\n**Container database (CDB):**\n\nFor a CDB, check the parameter in the root container:\n\n```sql\nSELECT VALUE FROM V$PARAMETER WHERE NAME = 'enable_goldengate_replication';\n```\n\nIf it is not set to `true`, you need to set it and **restart the database**:\n\n```sql\nALTER SYSTEM SET enable_goldengate_replication=true SCOPE=BOTH CONTAINER=ALL;\n```\n\n**Non-container database (Non-CDB):**\n\nFor a non-CDB, check the parameter in the database instance:\n\n```sql\nSELECT VALUE FROM V$PARAMETER WHERE NAME = 'enable_goldengate_replication';\n```\n\nIf it is not set to `true`, you need to set it and **restart the database**:\n\n```sql\nALTER SYSTEM SET enable_goldengate_replication=true SCOPE=BOTH;\n```\n\n\n\n### 3. Configure XStream\n\nUse the following SQL commands to configure XStream (using the\n[`chinook`](https://github.com/Redislabs-Solution-Architects/rdi-quickstart-postgres/tree/main)\nschema as an example):\n\n**non-RAC (single-instance):**\n\n```sql\n-- ======================================================================================================================================================\n-- !!!IMPORTANT!!!: \n-- In order to avoid Oracle downtime, please check if the LOG_MODE on your database is already set to `ARCHIVELOG` before executing the following commands: \n-- SELECT log_mode FROM v$database;\n-- If the LOG_MODE is already `ARCHIVELOG`, then you can skip the rest of the commands in this script\n-- ======================================================================================================================================================\nSQL\u003e shutdown immediate\nDatabase closed.\nDatabase dismounted.\nORACLE instance shut down.\nSQL\u003e startup mount\nORACLE instance started.\n\nTotal System Global Area 1476391776 bytes\nFixed Size     9134944 bytes\nVariable Size 1006632960 bytes\nDatabase Buffers   452984832 bytes\nRedo Buffers     7639040 bytes\nDatabase mounted.\nSQL\u003e alter database archivelog;\nSQL\u003e alter database open;\nSQL\u003e archive log list\nDatabase log mode       Archive Mode\nAutomatic archival       Enabled\nArchive destination       USE_DB_RECOVERY_FILE_DEST\nOldest online log sequence     10\nNext log sequence to archive   12\nCurrent log sequence       12\n\n-- Confirm the database is in ARCHIVELOG mode.\nSQL\u003e SELECT LOG_MODE FROM V$DATABASE;\n```\n\n**Oracle RAC (multitenant environment):**\n\n```sql\n-- ======================================================================================================================================================\n-- !!!IMPORTANT!!!: \n-- In order to avoid Oracle downtime, please check if the LOG_MODE on your database is already set to `ARCHIVELOG` before executing the following commands: \n-- SELECT log_mode FROM v$database;\n-- If the LOG_MODE is already `ARCHIVELOG`, then you can skip the rest of the commands in this script\n-- ======================================================================================================================================================\n\n-- Stop all database instances\nSQL\u003e srvctl stop database -d \u003cdb_Name\u003e\n\n-- Start the database in mount state.\nSQL\u003e srvctl start database -d \u003cdb_Name\u003e -o mount\n\n-- Enable archive log mode\nSQL\u003e alter database archivelog;\n\n-- Restart all database instances.\nSQL\u003e srvctl stop database -d \u003cdb_Name\u003e\nSQL\u003e srvctl start database -d \u003cdb_Name\u003e\n\n-- Confirm the database is in ARCHIVELOG mode.\nSQL\u003e SELECT LOG_MODE FROM V$DATABASE;\n```\n\n\n\n### 4. Enable supplemental logging\n\n**Container database (CDB):**\n\nEnable supplemental logging for the tables you want to capture or\nfor the entire database. This lets Debezium capture the state of\ndatabase rows before and after changes occur.\n\n```sql\nSQL\u003e ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;\n\nSQL\u003e alter session set container=orclpdb1;\n\nSQL\u003e ALTER TABLE CHINOOK.ALBUM ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.ARTIST ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.CUSTOMER ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.EMPLOYEE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.GENRE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.INVOICE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.INVOICELINE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.MEDIATYPE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.PLAYLIST ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.PLAYLISTTRACK ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.TRACK ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\n```\n\n\u003e [!NOTE]\n\u003e The example above uses `orclpdb1` as the PDB name. Replace it with the name of the pluggable database (PDB) that you use in your own environment.\n\n**Non-container database (Non-CDB):**\n\nEnable supplemental logging for the tables you want to capture or\nfor the entire database. This lets Debezium capture the state of\ndatabase rows before and after changes occur.\n\n```sql\nSQL\u003e ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;\n\nSQL\u003e ALTER TABLE CHINOOK.ALBUM ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.ARTIST ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.CUSTOMER ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.EMPLOYEE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.GENRE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.INVOICE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.INVOICELINE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.MEDIATYPE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.PLAYLIST ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.PLAYLISTTRACK ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\nSQL\u003e ALTER TABLE CHINOOK.TRACK ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\n```\n\n\n\n\u003e [!NOTE]\n\u003e You must configure supplemental logging explicitly for each table as shown \n\u003e above. Otherwise, only the original sync will be performed and no change data will be \n\u003e captured for the table.\n\n### 5. Create XStream users\n\n**Container database (CDB):**\n\n\u003e [!NOTE]\n\u003e The XStream user examples below use `ORCLCDB` as the CDB name and `ORCLPDB1`/`orclpdb1` as the PDB name in file paths and `ALTER SESSION SET CONTAINER` commands. Replace these with the CDB and PDB names from your own Oracle deployment.\n\nCreate an XStream administrator user with the following SQL:\n\n```sql\nsqlplus sys/\u003cPASSWORD\u003e as sysdba\n\nSQL\u003e ALTER SESSION SET CONTAINER=CDB$ROOT;\nSQL\u003e CREATE TABLESPACE xstream_adm_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/xstream_adm_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nSQL\u003e alter session set container=orclpdb1;\n\nSQL\u003e CREATE TABLESPACE xstream_adm_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/xstream_adm_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nSQL\u003e alter session set container=cdb$root;\n\nSQL\u003e CREATE USER c##dbzadmin IDENTIFIED BY dbz\n    DEFAULT TABLESPACE xstream_adm_tbs\n    QUOTA UNLIMITED ON xstream_adm_tbs\n    CONTAINER=ALL;\n\nSQL\u003e GRANT CREATE SESSION, SET CONTAINER TO c##dbzadmin CONTAINER=ALL;\n\nSQL\u003e BEGIN\n     DBMS_XSTREAM_AUTH.GRANT_ADMIN_PRIVILEGE(\n        grantee                 =\u003e 'c##dbzadmin',\n        privilege_type          =\u003e 'CAPTURE',\n        grant_select_privileges =\u003e TRUE,\n        container               =\u003e 'ALL'\n     );\n  END;\n  /\n```\n\nThen, create the XStream user:\n\n```sql\nsqlplus sys/\u003cPASSWORD\u003e as sysdba\n\nSQL\u003e CREATE TABLESPACE xstream_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/xstream_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nSQL\u003e alter session set container=orclpdb1;\n\nSQL\u003e CREATE TABLESPACE xstream_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/xstream_tbs.dbf'\n    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nSQL\u003e alter session set container=cdb$root;\n\nSQL\u003e CREATE USER c##dbzxsuser IDENTIFIED BY dbz\n    DEFAULT TABLESPACE xstream_tbs\n    QUOTA UNLIMITED ON xstream_tbs\n    CONTAINER=ALL;\n\nSQL\u003e GRANT CREATE SESSION TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT SET CONTAINER TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT SELECT ON V_$DATABASE to c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT FLASHBACK ANY TABLE TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT SELECT_CATALOG_ROLE TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT EXECUTE_CATALOG_ROLE TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT SELECT ANY TABLE TO c##dbzxsuser CONTAINER=ALL;\nSQL\u003e GRANT LOCK ANY TABLE TO c##dbzxsuser CONTAINER=ALL;\n```\n\n\u003e [!NOTE]\n\u003e If you are using the\n\u003e [Debezium XStream documentation](https://debezium.io/documentation/reference/stable/connectors/oracle.html#creating-xstream-users-for-the-connector),\n\u003e you should note that it misses out the last two GRANT statements shown above:\n\u003e\n\u003e ```sql\n\u003e GRANT SELECT ANY TABLE TO c##dbzxsuser CONTAINER=ALL;\n\u003e GRANT LOCK ANY TABLE TO c##dbzxsuser CONTAINER=ALL;\n\u003e ```\n\u003e\n\u003e However, without these, no tables can be read by Debezium, so neither the initial snapshot nor any subsequent updates will produce any data.\n\n**Non-container database (Non-CDB):**\n\n\u003e [!NOTE]\n\u003e The non-CDB architecture is deprecated in Oracle Database 12c and discontinued in Oracle Database 20c.\n\nFor a non-container (non-CDB) Oracle database:\n\n- You have a single database with no containers.\n- Users are regular database users without the `C##` prefix.\n- Application data is stored directly in the database.\n- You do not use `ALTER SESSION SET CONTAINER` statements or `CONTAINER=ALL` clauses.\n\n**Create XStream users and tablespaces (non-CDB)**\u003cbr/\u003e\n\nRun the following script as the `sys` user:\n\n```sql\n-- =====================================================\n-- Create XStream Users - FOR NON-CDB ENVIRONMENT\n-- =====================================================\n-- This script creates the XStream administrator and user accounts\n-- Run as: sqlplus sys/\u003cPASSWORD\u003e as sysdba\n-- =====================================================\n\n-- Step 1: Create XStream Administrator Tablespace\nCREATE TABLESPACE xstream_adm_tbs DATAFILE '/u01/app/oracle/oradata/ORCL/xstream_adm_tbs.dbf'\n  SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nPROMPT Tablespace xstream_adm_tbs created\n\n-- Step 2: Create XStream Administrator User\nCREATE USER dbzadmin IDENTIFIED BY dbz\n  DEFAULT TABLESPACE xstream_adm_tbs\n  QUOTA UNLIMITED ON xstream_adm_tbs;\n\nGRANT CREATE SESSION TO dbzadmin;\n\nPROMPT User dbzadmin created\n\n-- Step 3: Grant XStream Admin Privileges\nBEGIN\n  DBMS_XSTREAM_AUTH.GRANT_ADMIN_PRIVILEGE(\n    grantee                 =\u003e 'dbzadmin',\n    privilege_type          =\u003e 'CAPTURE',\n    grant_select_privileges =\u003e TRUE\n  );\nEND;\n/\n\nPROMPT XStream admin privileges granted to dbzadmin\n\n-- Step 4: Create XStream User Tablespace\nCREATE TABLESPACE xstream_tbs DATAFILE '/u01/app/oracle/oradata/ORCL/xstream_tbs.dbf'\n  SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;\n\nPROMPT Tablespace xstream_tbs created\n\n-- Step 5: Create XStream User\nCREATE USER dbzxsuser IDENTIFIED BY dbz\n  DEFAULT TABLESPACE xstream_tbs\n  QUOTA UNLIMITED ON xstream_tbs;\n\nPROMPT User dbzxsuser created\n\n-- Step 6: Grant necessary privileges to XStream User\nGRANT CREATE SESSION TO dbzxsuser;\nGRANT SELECT ON V_$DATABASE TO dbzxsuser;\nGRANT FLASHBACK ANY TABLE TO dbzxsuser;\nGRANT SELECT_CATALOG_ROLE TO dbzxsuser;\nGRANT EXECUTE_CATALOG_ROLE TO dbzxsuser;\nGRANT SELECT ANY TABLE TO dbzxsuser;\nGRANT LOCK ANY TABLE TO dbzxsuser;\n\nPROMPT Privileges granted to dbzxsuser\n\n-- Verification: Check users were created\nSELECT username, account_status, default_tablespace \nFROM dba_users \nWHERE username IN ('DBZADMIN', 'DBZXSUSER');\n\nPROMPT\nPROMPT =====================================================\nPROMPT XStream Users Created Successfully!\nPROMPT =====================================================\nPROMPT Created users:\nPROMPT   - dbzadmin (XStream Administrator)\nPROMPT   - dbzxsuser (XStream User)\nPROMPT\nPROMPT Next step:\nPROMPT Run 03_create_xstream_outbound.sql to create outbound server\nPROMPT =====================================================\n```\n\nThis script creates:\n\n- The `xstream_adm_tbs` tablespace and `dbzadmin` XStream administrator user.\n- The `xstream_tbs` tablespace and `dbzxsuser` XStream connect user.\n\n\n\n### 6. Create an XStream outbound server\n\nCreate the outbound server with the following SQL.\n\n**Container database (CDB):**\n\n\u003e [!NOTE]\n\u003e In this example, `ORCLCDB` is the CDB service name and `orclpdb1` is the PDB name. Replace them with the appropriate service and PDB names for your own environment.\n\nNote that you must connect as the `c##dbzadmin` user created in the previous step,\nnot the `sys` user:\n\n```bash\nsqlplus c##dbzadmin/dbz@localhost:1521/ORCLCDB\n```\n\n```sql\n-- =====================================================\n-- Create XStream Outbound Server\n-- =====================================================\n-- This script creates the XStream outbound server for CDC\n-- Run as: sqlplus c##dbzadmin/dbz@localhost:1521/ORCLCDB\n-- =====================================================\n\n-- Step 1: Create XStream Outbound Server\nDECLARE\n  tables  DBMS_UTILITY.UNCL_ARRAY;\n  schemas DBMS_UTILITY.UNCL_ARRAY;\nBEGIN\n  tables(1)  := NULL;\n  schemas(1) := 'C##DBZUSER';\n  \n  DBMS_XSTREAM_ADM.CREATE_OUTBOUND(\n    server_name           =\u003e 'dbzxout',\n    source_container_name =\u003e 'XEPDB1',\n    table_names           =\u003e tables,\n    schema_names          =\u003e schemas\n  );\nEND;\n/\n\n-- Step 2: Configure XStream User to connect to outbound server\n-- This must be run as sys user\nCONNECT sys/oracle AS SYSDBA\n\nBEGIN\n  DBMS_XSTREAM_ADM.ALTER_OUTBOUND(\n    server_name  =\u003e 'dbzxout',\n    connect_user =\u003e 'c##dbzxsuser'\n  );\nEND;\n/\n\n-- Verification: Check outbound server was created\nSELECT server_name, source_database, capture_name, capture_user, connect_user, queue_owner, queue_name\nFROM dba_xstream_outbound;\n\n-- Verification: Check capture process\nSELECT capture_name, status, capture_type, source_database\nFROM dba_capture;\n\nPROMPT\nPROMPT =====================================================\nPROMPT XStream Outbound Server Created Successfully!\nPROMPT =====================================================\nPROMPT Server name: dbzxout\nPROMPT Schema: C##DBZUSER\nPROMPT PDB: XEPDB1\nPROMPT =====================================================\n```\n\n-\n\n**Non-container database (Non-CDB):**\n\nNote that you must connect as the `dbzadmin` user created in the previous step,\nnot the `sys` user:\n\n```bash\nsqlplus dbzadmin/dbz@localhost:1521/ORCL\n```\n\n```sql\n-- =====================================================\n-- Create XStream Outbound Server - FOR NON-CDB ENVIRONMENT\n-- =====================================================\n-- This script creates the XStream outbound server for CDC\n-- Run as: sqlplus dbzadmin/dbz@localhost:1521/ORCL\n-- =====================================================\n\n-- Step 1: Create XStream Outbound Server\nDECLARE\n  tables  DBMS_UTILITY.UNCL_ARRAY;\n  schemas DBMS_UTILITY.UNCL_ARRAY;\nBEGIN\n  tables(1)  := NULL;\n  schemas(1) := 'chinook';  -- Replace with actual schema name\n  \n  DBMS_XSTREAM_ADM.CREATE_OUTBOUND(\n    server_name     =\u003e 'dbzxout',\n    table_names     =\u003e tables,\n    schema_names    =\u003e schemas\n  );\nEND;\n/\n\nPROMPT XStream outbound server created\n\n-- Step 2: Configure XStream User to connect to outbound server\n-- This must be run as sys user\nCONNECT sys/\u003cPASSWORD\u003e AS SYSDBA\n\nBEGIN\n  DBMS_XSTREAM_ADM.ALTER_OUTBOUND(\n    server_name  =\u003e 'dbzxout',\n    connect_user =\u003e 'dbzxsuser'\n  );\nEND;\n/\n\nPROMPT Connect user configured\n\n-- Verification: Check outbound server was created\nSELECT server_name, source_database, capture_name, capture_user, connect_user, queue_owner, queue_name\nFROM dba_xstream_outbound;\n\n-- Verification: Check capture process\nSELECT capture_name, status, capture_type, source_database\nFROM dba_capture;\n\nPROMPT\nPROMPT =====================================================\nPROMPT XStream Outbound Server Created Successfully!\nPROMPT =====================================================\nPROMPT Server name: dbzxout\nPROMPT =====================================================\n```\n\n\n\n### 7. Add a custom Docker image for the Debezium server\n\nTo support XStream connector, you must create a custom [Docker](https://www.docker.com/) image that includes the required Instant Client package libraries for Linux x64 from the Oracle website.\n\n1.  On the Docker machine, download the Instant Client package for Linux x64 from the Oracle website\n\n    ```bash\n    wget https://download.oracle.com/otn_software/linux/instantclient/2380000/instantclient-basic-linux.x64-23.8.0.25.04.zip\n    ```\n\n1.  Unzip it to the `./dbz-ora` directory:\n\n    ```bash\n    unzip instantclient-basic-linux.x64-23.8.0.25.04.zip -d ./dbz-ora\n    ```\n\n1.  Create a `Dockerfile` in the `./dbz-ora` directory with the following contents:\n\n    ```docker\n    FROM debezium/server:3.0.8.Final\n\n    USER root\n\n    RUN microdnf -y install libaio \\\n    \u0026\u0026 microdnf clean all \\\n    \u0026\u0026 mkdir -p /opt/oracle/instant_client \\\n    \u0026\u0026 rm -f /debezium/lib/ojdbc11*.jar\n\n    COPY instantclient_23_8/* /opt/oracle/instant_client\n\n    USER jboss\n\n    COPY instantclient_23_8/xstreams.jar /debezium/lib\n    COPY instantclient_23_8/ojdbc11.jar /debezium/lib\n\n    ENV LD_LIBRARY_PATH=/opt/oracle/instant_client\n    ```\n\n1.  Create the custom image:\n\n    ```bash\n    docker build -t dbz-ora dbz-ora\n    ```\n\n1.  Add the image to the K3s image registry using the following commands:\n\n    ```bash\n    docker tag dbz-ora quay.io/debezium/server:3.0.8.Final\n    docker image save quay.io/debezium/server:3.0.8.Final -o dbz3.0.8-xstream-linux-amd.tar\n    sudo k3s ctr images import dbz3.0.8-xstream-linux-amd.tar all\n    ```\n\n### 8. Make RDI use the custom image (VM installation)\n\nEdit the `rdi-operator` configmap:\n\n```bash\nkubectl edit configmap rdi-operator -n rdi\n```\n\nIn the editor, find the collector section and change the image settings:\n\n```yaml\n      collector:\n        image:\n          pullPolicy: IfNotPresent\n          registry: docker.io # change this to `quay.io`\n          repository: redislabs/debezium-server # Change this to `debezium/server`\n          tag: 3.0.8.Final-rdi.1 # Change this to `3.0.8.Final`\n```\n\nSave the configmap. Once it is saved, the operator will restart automatically and will apply the changes.\n\n\u003e [!NOTE]\n\u003e After upgrading to another RDI version,\n\u003e the changes to the configmap will be lost. You must repeat the above steps after each upgrade.\n\n### 9. Enable the Oracle configuration in RDI\n\nFinally, you must update your `config.yaml` file to enable XStream.\nThe example below shows the relevant parts of the `sources` section:\n\n```yaml\nsources:\n  oracle:\n    type: cdc\n    logging:\n      level: info\n    connection:\n      type: oracle\n      host: host.docker.internal\n      port: 1521\n      user: ${SOURCE_DB_USERNAME}\n      password: ${SOURCE_DB_PASSWORD}\n    advanced:\n      source:\n        database.dbname: ORCLCDB\n        database.pdb.name: ORCLPDB1\n        database.connection.adapter: xstream\n        database.out.server.name: dbzxout\n```\n\n\u003e [!NOTE]\n\u003e The values `ORCLCDB` and `ORCLPDB1` in the example above are sample CDB and PDB names. Set `database.dbname` and `database.pdb.name` to the CDB and PDB names for your own Oracle database.\n\nSee the\n[Debezium Oracle documentation](https://debezium.io/documentation/reference/stable/connectors/oracle.html#oracle-connector-properties)\nfor a full list of properties you can use in the `advanced.source` subsection.\n\n### 10. Configuration is complete {#xstream-complete}\n\nAfter you have followed the steps above, your Oracle database is ready\nfor Debezium to use.\n\n## Support for Oracle XMLTYPE columns (optional)\n\nIf your Oracle database contains tables with columns of type\n[`XMLTYPE`](https://docs.oracle.com/en/database/oracle/oracle-database/21/arpls/XMLTYPE.html),\nyou must configure additional libraries for Debezium Server to process these columns correctly.\n\n### Create a custom Debezium Server image\n\nTo support `XMLTYPE` columns, you must create a custom [Docker](https://www.docker.com/) image\nthat includes the required Oracle XML libraries.\n\n1. Download the required libraries from Maven Central:\n\n   ```bash\n   mkdir xml\n   cd xml\n   wget https://repo.maven.apache.org/maven2/com/oracle/database/xml/xdb/19.27.0.0/xdb-19.27.0.0.jar\n   wget https://repo.maven.apache.org/maven2/com/oracle/database/xml/xmlparserv2/19.27.0.0/xmlparserv2-19.27.0.0.jar\n   mv xdb-19.27.0.0.jar xdb.jar\n   mv xmlparserv2-19.27.0.0.jar xmlparserv2.jar\n   ```\n\n2. Create a `Dockerfile` in the same directory:\n\n   ```dockerfile\n   FROM quay.io/debezium/server:3.0.8.Final\n\n   USER root\n\n   COPY xdb.jar /debezium/lib\n   COPY xmlparserv2.jar /debezium/lib\n   ```\n\n3. Build the custom image:\n\n   ```bash\n   cd ..\n   docker build -t dbz-xml xml\n   docker tag dbz-xml quay.io/debezium/server:3.0.8.Final\n   docker image save quay.io/debezium/server:3.0.8.Final -o dbz3.0.8-xml-linux-amd.tar\n   ```\n\n4. Add the image to your K3s image repository:\n\n   ```bash\n   sudo k3s ctr images import dbz3.0.8-xml-linux-amd.tar all\n   ```\n\n### Configure RDI for XMLTYPE support\n\nIn your RDI configuration file, set the `lob.enabled` property to `true` in the\n`advanced.source` section:\n\n```yaml\nsources:\n  oracle:\n    type: cdc\n    logging:\n      level: info\n    connection:\n      type: oracle\n      host: oracle\n      port: 1521\n      user: ${SOURCE_DB_USERNAME}\n      password: ${SOURCE_DB_PASSWORD}\n      database: ORCLCDB\n    advanced:\n      source:\n        database.pdb.name: ORCLPDB1\n        lob.enabled: true\n```\n\n\u003e [!NOTE]\n\u003e The XMLTYPE configuration example uses `ORCLCDB` as the CDB name and `ORCLPDB1` as the PDB name. Replace these with your actual CDB and PDB names when configuring XMLTYPE support.\n\n### Test XMLTYPE support\n\nYou can create a test table to verify that `XMLTYPE` columns work correctly\n(using the\n[`CHINOOK`](https://github.com/Redislabs-Solution-Architects/rdi-quickstart-postgres/tree/main)\nschema as an example):\n\n```sql\nCREATE TABLE tab1 (\n  xmlid INT NOT NULL,\n  col1  SYS.XMLTYPE,\n  CONSTRAINT PK_tab1 PRIMARY KEY (xmlid)\n);\n\nDECLARE\n  v_xml   SYS.XMLTYPE;\n  v_doc   CLOB;\nBEGIN\n  -- XMLTYPE created from a CLOB\n  v_doc := '\u003c?xml version=\"1.0\"?\u003e' || Chr(10) || ' \u003cTABLE_NAME\u003eMY_TABLE\u003c/TABLE_NAME\u003e';\n  v_xml := SYS.XMLTYPE.createXML(v_doc);\n\n  INSERT INTO tab1 (xmlid, col1) VALUES (1, v_xml);\n\n  -- XMLTYPE created from a query\n  SELECT SYS_XMLGEN(table_name)\n  INTO   v_xml\n  FROM   user_tables\n  WHERE  rownum = 1;\n\n  INSERT INTO tab1 (xmlid, col1) VALUES (2, v_xml);\n\n  COMMIT;\nEND;\n/\n\nALTER TABLE CHINOOK.TAB1 ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;\n```\n\nAfter you run an initial\n[snapshot](https://redis.io/docs/latest/integrate/redis-data-integration/1.19.1/data-pipelines#pipeline-lifecycle),\nthe XML data appears in your Redis target database:\n\n![images/rdi/ingest/xmltype-example.webp](https://redis.io/docs/latest/images/rdi/ingest/xmltype-example.webp)\n\n## FAQ\n\n### How does CDB differ from Non-CDB?\n\n**CDB (Container Database – multitenant)**\n\n- Root container `CDB$ROOT` plus one or more pluggable databases (PDBs).\n- Common users (for example `C##DBZADMIN`, `C##DBZXSUSER`) exist across all containers.\n- Application data lives in PDBs.\n- Many XStream-related operations use `CONTAINER=ALL` and `ALTER SESSION SET CONTAINER`.\n\n**Non-CDB (traditional)**\n\n- Single database, no containers.\n- Users are regular database users without the `C##` prefix (for example `DBZADMIN`, `DBZXSUSER`).\n- Application data lives directly in that single database.\n- No `CONTAINER=ALL` or `ALTER SESSION SET CONTAINER` clauses are required.\n\nFrom an RDI/Debezium point of view, both models are supported; the main differences are in the user names you create and whether you need container-related clauses in the SQL.\n\n### How does single-instance differ from RAC?\n\n**Single-instance**\n\n- One Oracle instance running on one server.\n- You run the LogMiner/XStream setup scripts once.\n- All configuration (users, tablespaces, outbound server, logging) is stored in that database instance.\n\n**RAC (Real Application Clusters)**\n\n- Multiple instances (nodes) share the same database and storage.\n- You still run the XStream setup only once on any one node.\n- All nodes share the same:\n  - Database files\n  - Archive logs\n  - XStream outbound server\n  - Capture process\n\nImportant RAC points:\n\n- Archive log mode is enabled at the database level and applies to all nodes.\n- Tablespaces you create are in shared storage and visible from all nodes.\n- Users you create exist in the shared database and can connect through any node.\n- Debezium/RDI can connect to any RAC node or to a SCAN address; it does not need a specific node.\n\n### In RAC setups, do you need to execute steps on all nodes?\n\nNo. The XStream configuration is database-level, so you execute the setup once on any node:\n\n- Enable archive log mode: once (affects the whole database).\n- Create XStream tablespaces: once (on shared storage).\n- Create XStream users: once (in the shared database).\n- Create the XStream outbound server: once (visible from all nodes).\n- Enable supplemental logging: once (database-wide).\n\nYou may run client connection tests from multiple nodes, but the actual administrative steps only need to be executed once.\n\n### Why are two XStream tablespaces required?\n\nXStream is not just reading your tables - it's storing its own data:\n\n**Customer's existing tablespace**:\n\n```mermaid\ngraph TB\n    USERS[\"\u003cb\u003eUSERS\u003c/b\u003e\u003cbr/\u003e\u003cbr/\u003e- CUSTOMERS table\u003cbr/\u003e- ORDERS table\u003cbr/\u003e- PRODUCTS table\u003cbr/\u003e- TRANSACTIONS table\u003cbr/\u003e\u003cbr/\u003e(Application data)\"]\n```\n\n**XStream tablespaces**:\n\n```mermaid\ngraph TB\n    ADM[\"\u003cb\u003eXSTREAM_ADM_TBS\u003c/b\u003e\u003cbr/\u003e\u003cbr/\u003e- Capture process metadata\u003cbr/\u003e- Outbound server config\u003cbr/\u003e- Checkpoint information\u003cbr/\u003e- Position tracking\"]\n    USER_TS[\"\u003cb\u003eXSTREAM_TBS\u003c/b\u003e\u003cbr/\u003e\u003cbr/\u003e- LCR Queue change records\u003cbr/\u003e- Buffered changes\u003cbr/\u003e- Transaction state\"]\n```\n\n#### Real Example: What Gets Stored Where\n\nScenario: Customer has CUSTOMERS table\n\nCustomer's existing tablespace (USERS):\n```sql\n-- Application data\nSELECT * FROM MY_APP.CUSTOMERS;\n-- Returns: customer_id, name, address, balance, etc.\n```\n\nXStream tablespaces (NEW):\n```sql\n-- XStream metadata (in XSTREAM_ADM_TBS)\nSELECT capture_name, status, start_scn, checkpoint_scn \nFROM dba_capture;\n-- Returns: dbzxout_capture, ENABLED, 12345678, 12345690\n\n-- XStream queue (in XSTREAM_TBS)\nSELECT queue_name, enqueue_time, dequeue_time, state\nFROM dba_queues;\n-- Returns: dbzxout_queue, \u003ctimestamp\u003e, \u003ctimestamp\u003e, READY\n```\n\n#### Size Comparison\n\nCustomer's Application Tablespaces:\n\n```sql\n-- Typical size: Large\nSELECT tablespace_name, \n       ROUND(SUM(bytes)/1024/1024/1024, 2) AS size_gb\nFROM dba_data_files\nWHERE tablespace_name = 'USERS'\nGROUP BY tablespace_name;\n\n-- Result: 50 GB, 100 GB, 500 GB, etc.\n```\n\nXStream Tablespaces:\n\n```sql\n-- Typical size: Small\nSELECT tablespace_name, \n       ROUND(SUM(bytes)/1024/1024, 2) AS size_mb\nFROM dba_data_files\nWHERE tablespace_name IN ('XSTREAM_ADM_TBS', 'XSTREAM_TBS')\nGROUP BY tablespace_name;\n\n-- Result: \n-- XSTREAM_ADM_TBS: 100-500 MB\n-- XSTREAM_TBS: 500 MB - 2 GB (depends on queue size)\n```\n\n#### General Recommendations\n\nThis guide uses two separate tablespaces:\n\n- `xstream_adm_tbs` – XStream administrator tablespace.\n- `xstream_tbs` – XStream user (connect) tablespace.\n\nThey serve different purposes and follow the principle of least privilege.\n\n**1. Separation of concerns and security**\n\n- *Administrator tablespace (`xstream_adm_tbs`)*\n  - Used by the XStream admin user (for example `C##DBZADMIN` or `DBZADMIN`).\n  - Stores XStream metadata and control structures:\n    - Capture process metadata\n    - Outbound server configuration\n    - Queue tables and queues\n    - Other XStream internal objects\n  - Belongs to a highly privileged user that can create and manage XStream objects.\n\n- *User tablespace (`xstream_tbs`)*\n  - Used by the XStream connect user (for example `C##DBZXSUSER` or `DBZXSUSER`).\n  - Lower-privileged account used by Debezium/RDI to read changes.\n  - Keeps operational data and temporary objects separate from admin metadata.\n\n**2. Resource management**\n\nHaving two tablespaces lets you:\n\n- Monitor space usage separately for admin vs user workloads.\n- Allow for different growth patterns (admin metadata typically grows more slowly).\n- Apply separate quotas per user/tablespace.\n- Tune storage parameters differently for each tablespace if needed.\n\n**3. Operational benefits**\n\n- Backup and recovery:\n  - You can back up or restore admin and user data independently.\n  - Critical XStream metadata is isolated in its own tablespace.\n- Maintenance and troubleshooting:\n  - You can perform maintenance on one tablespace without affecting the other.\n  - Easier to diagnose which part of the XStream setup is consuming space.\n- Security and auditing:\n  - Clear separation of administrative vs operational data.\n  - Easier to audit which users access which objects.\n\n**4. Can you use a single tablespace?**\n\nTechnically you could place both users in a single tablespace, but this is not recommended for production:\n\n- It weakens separation of duties and least-privilege design.\n- It makes monitoring and capacity planning harder.\n- It mixes admin metadata and application-facing data in one place.\n\nOracle and Debezium best practices recommend separating admin and user workloads into different tablespaces.\n\n### What is the XStream outbound server?\n\nThe XStream outbound server is the component that streams database changes out of Oracle in a supported way. It:\n\n- Captures committed changes (INSERT, UPDATE, DELETE) from redo logs.\n- Converts them into logical change records (LCRs).\n- Exposes an API that external consumers such as Debezium/RDI use.\n\n**High-level architecture**\n\n```mermaid {width=\"100%\"}\ngraph LR\n    RedoLogs[\"\u003cb\u003eRedo Logs\u003c/b\u003e\"]\n    Capture[\"\u003cb\u003eCapture Process\u003c/b\u003e\"]\n    Queue[\"\u003cb\u003eQueue\u003c/b\u003e\"]\n    Outbound[\"\u003cb\u003eXStream Outbound\u003cbr/\u003eServer\u003c/b\u003e\"]\n    Consumer[\"\u003cb\u003eDebezium/RDI\u003c/b\u003e\"]\n\n    RedoLogs --\u003e Capture\n    Capture --\u003e Queue\n    Queue --\u003e Outbound\n    Outbound --\u003e Consumer\n```\n\n**Key components**\n\n- *Redo logs*: Contain the physical change records for the database.\n- *Capture process*: Mines redo logs and turns them into logical change records.\n- *Queue*: Temporarily stores captured changes.\n- *XStream outbound server* (for example `DBZXOUT`):\n  - Provides the streaming interface for consumers.\n  - Applies filters (schemas/tables) configured when you create it.\n- *Connect user* (for example `C##DBZXSUSER` or `DBZXSUSER`):\n  - The user Debezium/RDI connects as.\n  - Reads changes from the outbound server.\n\n**Why it is needed**\n\nWithout an XStream outbound server:\n\n- There is no supported, structured API for consuming change events.\n- You would have to parse redo logs directly, which is complex and unsupported.\n- You lose built-in filtering, transaction grouping, and restart/resume semantics.\n\nWith an XStream outbound server:\n\n- Changes are available in near real time.\n- You can capture only selected schemas/tables.\n- Debezium/RDI uses Oracle’s supported XStream API.\n- Transactions are preserved and grouped correctly.\n- Offsets/positions allow clean resume after restarts.\n- Multiple consumers can be attached to the same outbound server if needed.\n",
  "tags": ["docs","integrate","rs","rdi"],
  "last_updated": "2026-09-19T17:55:58-07:00"
}
