Skip to main content

Oracle to MySQL Database Link Setup Guide

Oracle to MySQL database link setup overview

Introduction

In Oracle, a heterogeneous database link allows you to connect to non-Oracle databases from an Oracle database. This is useful for querying and manipulating data across different database systems, such as SQL Server, MySQL, or others, without needing a separate ETL process just to read data. This article walks through creating an Oracle to MySQL database link step by step, using Oracle's Heterogeneous Services and the ODBC driver for MySQL.

Prerequisites

  • Network connectivity established between the source and target environments. Verify with ping or telnet.
  • The MySQL ODBC connector package installed on the Oracle DB server. Verify with rpm -qa | grep mysql. You should see packages similar to:
    mysql-community-client-8.0.35-1.el8.x86_64
    mysql-connector-odbc-8.0.26-1.el7.x86_64

Environment Used in This Guide

## Source Target
Database Oracle 19c MySQL
IP 192.168.80.33 10.192.225.144
DB Name ORCLPRD mysql_db
Port 1521 5544
Username sys datalake

Step 1: Install the MySQL ODBC Connector

The heterogeneous connection relies on an ODBC driver to translate between Oracle's Heterogeneous Services and MySQL's native protocol. Install the connector package, either via yum or by downloading the RPM directly from Oracle Yum and installing it manually with rpm -ivh "package" as root.


[root@oracle01~]# yum install mysql-connector-odbc-8.0.26-1.el7.x86_64
Loaded plugins: langpacks, ulninfo
Resolving Dependencies
--> Running transaction check
---> Package mysql-connector-odbc.x86_64 0:8.0.26-1.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
====================================================================================
 Package                                      Arch                           Version                                Repository                                          Size
====================================================================================
Installing:
 mysql-connector-odbc                         x86_64                         8.0.26-1.el7                           mysql-connectors-community                         4.1M

Transaction Summary
====================================================================================
Install  1 Package
Total download size: 4.1 M
Installed size: 22 M
Is this ok [y/d/N]: y
Downloading packages:
mysql-connector-odbc-8.0.26-1.el7.x86_64.rpm                                                                                                          | 4.1 MB  00:00:02
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : mysql-connector-odbc-8.0.26-1.el7.x86_64                                                                                                                  1/1
Success: Usage count is 1
Success: Usage count is 1
  Verifying  : mysql-connector-odbc-8.0.26-1.el7.x86_64                                                                                                                  1/1
Installed:
  mysql-connector-odbc.x86_64 0:8.0.26-1.el7
Complete!
[root@oracle01~]#

Install the mysql-community-client package the same way, it provides the mysql command-line client we'll use later to independently verify connectivity.

Step 2: Create the ODBC Data Source

Create or edit /etc/odbc.ini to define the MySQL data source. If a file already exists, back it up first before adding these entries, and note this typically requires root access to edit.


[oracle@oracle01 admin]$ cat /etc/odbc.ini
[mysql_db]
Description = MYSQL
Driver = /usr/lib64/libmyodbc8a.so
Server = 10.192.225.144
User = datalake
Password = YourP@ssw0rd
Port = 5544
Database = mysql_db
OPTION = 0
TRACE = OFF
[oracle@oracle01 admin]$

Step 3: Create the Heterogeneous Services Init File

Navigate to $ORACLE_HOME/hs/admin and create a file named to match your data source, in the format initDATASOURCENAME.ora. This file tells Oracle's Heterogeneous Services agent how to connect through the ODBC driver.


[oracle@oracle01 admin]$ pwd
/u01/app/oracle/product/19.0.0/dbhome_1/hs/admin
[oracle@oracle01 admin]$ cat initmysql_db.ora
HS_FDS_CONNECT_INFO = mysql_db
HS_FDS_TRACE_LEVEL = off
HS_FDS_SHAREABLE_NAME=/usr/lib64/libodbc.so
HS_FDS_FETCH_ROWS = 1
HS_FDS_SUPPORT_STATISTICS=FALSE
HS_LANGUAGE=american_america.we8iso8859P1
HS_NLS_NCHAR=UCS2

Step 4: Configure the Listener and TNS Entries

Add a new SID_DESC entry to listener.ora using the dg4odbc program, this is what tells the listener to route connections for this service through the heterogeneous gateway rather than a normal Oracle instance. Then add a matching TNS entry in tnsnames.ora with (HS=OK), which marks it as a heterogeneous services connection.


[oracle@oracle01 admin]$ cat listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/19.0.0/dbhome_1/network/admin/listener.ora
# Generated by Oracle configuration tools.
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oracle01)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

SID_LIST_LISTENER =
        (SID_LIST =
                (SID_DESC =
                        (GLOBAL_DBNAME = ORCLPRD)
                        (ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1)
                        (SID_NAME = ORCLPRD)
                )
                (SID_DESC=
                        (SID_NAME=mysql_db)
                        (ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1)
                        (PROGRAM=dg4odbc)
                        (ENV="LD_LIBRARY_PATH=/usr/lib64:/u01/app/oracle/product/19.0.0/dbhome_1/lib")
                )
        )

[oracle@oracle01 admin]$ cat tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/19.0.0/dbhome_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

ORCLPRD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracle01)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORCLPRD)
    )
  )

mysql_db =
   (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST=192.168.80.33)(PORT=1521)) # IP Oracle Database
      (CONNECT_DATA=(SID=mysql_db))
      (HS=OK)
    )
[oracle@oracle01 admin]$

After saving these files, reload the listener with lsnrctl reload LISTENER so it picks up the new service. Alternatively, you can run a separate listener on a different port dedicated to MySQL connections, in which case you'd only need to start the new listener rather than restart the existing one.

Step 5: Verify the Listener and TNS Connectivity

Confirm the new service is registered with the listener, then use tnsping to verify the TNS alias resolves and the target is reachable.


[oracle@oracle01 admin]$ lsnrctl status
LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 20-FEB-2025 11:50:17
Copyright (c) 1991, 2022, Oracle.  All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle01)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                20-FEB-2025 11:50:17
Uptime                    0 days 8 hr. 10 min. 48 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/19.0.0/dbhome_1/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/oracle01/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=oracle01)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Services Summary...
Service "ORCLPRD" has 2 instance(s).
  Instance "ORCLPRD", status UNKNOWN, has 1 handler(s) for this service...
  Instance "ORCLPRD", status READY, has 1 handler(s) for this service...
Service "ORCLPRDXDB" has 1 instance(s).
  Instance "ORCLPRD", status READY, has 1 handler(s) for this service...
Service "mysql_db" has 1 instance(s).
  Instance "mysql_db", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
[oracle@oracle01 admin]$ 
[oracle@oracle01 admin]$ tnsping "mysql_db"
TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 20-FEB-2025 11:51:07
Copyright (c) 1997, 2022, Oracle.  All rights reserved.
Used parameter files:
/u01/app/oracle/product/19.0.0/dbhome_1/network/admin/sqlnet.ora
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST=192.168.80.33)(PORT=1521)) (CONNECT_DATA=(SID=mysql_db)) (HS=OK))
OK (0 msec)

Step 6: Test the ODBC Connection Independently

Before creating the database link itself, it's worth confirming the ODBC connection and raw MySQL connection both work on their own. This isolates whether any later issue is with the database link configuration or with the underlying connectivity.


[oracle@oracle01 ~]$ isql -v mysql_db
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> show databases
+-----------------------------------------------------------------+
| Database                                                        |
+-----------------------------------------------------------------+
| information_schema                                              |
| daily_schedular_db                                              |
| mysql_db                                                        |
| mysql                                                           |
| performance_schema                                              |
| test                                                            |
+-----------------------------------------------------------------+
SQLRowCount returns 6
6 rows fetched
SQL> 

[oracle@oracle01 ~]$ mysql -udatalake -p -h10.192.225.144 -P5544
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1094140
Server version: 5.6.47 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| daily_schedular_db |
| mysql_db           |
| mysql              |
| performance_schema |
| test                |
+--------------------+
6 rows in set (0.00 sec)

Quick reference for the mysql command flags used above: -u is the user, -p prompts for the password, -h is the host, -P is the port, and -v (used with isql) enables verbose output.

Step 7: Create the Database Link

With connectivity confirmed at every layer, we can finally create the database link itself. If you want a private database link instead, log into Oracle as the specific user who should own it. Here we're creating a public link, available to any user with the appropriate grants.


[oracle@oracle01 ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Thu Feb 20 12:07:08 2025
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> CREATE PUBLIC DATABASE LINK ORACLE_TO_MYSQL_DBLINK CONNECT TO "datalake" IDENTIFIED BY "YourP@ssw0rd" USING 'mysql_db';
Database link created.

SQL> set lines 333 pages 333
SQL> col OWNER for a20
SQL> col DB_LINK for a80
SQL> col USERNAME for a20
SQL> col HOST for a30
SQL> col CREATED for a10
SQL> select OWNER, DB_LINK, USERNAME, HOST, CREATED from dba_db_links;

OWNER                DB_LINK                               USERNAME             HOST                           CREATED
-------------------- -------------------------------------- -------------------- ------------------------------ ----------
SYS                  SYS_HUB                                SEEDDATA                                          17-APR-19
PUBLIC               ORACLE_TO_MYSQL_DBLINK                 datalake             mysql_db                       20-FEB-25

SQL> select sysdate from dual@ORACLE_TO_MYSQL_DBLINK;
SYSDATE
---------
20-FEB-25

SQL> select * from dual@ORACLE_TO_MYSQL_DBLINK;
D
-
X

SQL>

The successful queries against dual@ORACLE_TO_MYSQL_DBLINK confirm the link is working end to end, Oracle is routing the query through Heterogeneous Services, over ODBC, to MySQL, and getting a valid response back.

What Next --> Oracle to MSSQL Server DB Link

Thank you for reading!

I hope this content has been helpful to you. Your feedback and suggestions are always welcome. Feel free to leave a comment or reach out with any queries.

Abhishek Shrivastava

Oracle DBA with hands-on experience managing production Data Guard, RAC, GoldenGate, and APEX environments. I write practical, tested installation and troubleshooting guides based on real deployment work.

📧 Email: oraeasyy@gmail.com
🌐 Website: www.oraeasy.com

Follow Us

Comments