On trouve différents tutoriels, la plupart en anglais, au sujet de la création d'un database_link dans Oracle pour accéder à une base MySQL. L'un parle du cas spécifique de l'accès à une base MariaDB mais ses exemples de code m'ont posé quelques soucis de compréhension entraînant par la suite un refus de fonctionnement et quelques prises de tête pendant pas mal de temps.
Je vais donc décrire ici pas à pas ce qu'il faut faire pour que ça fonctionne.
Nota :
Pour les configurations ci-après, je me suis servi de mes fichiers de configuration réels que j'ai ensuite annonymisés. Si vous rencontrez des erreurs, n'hésitez pas à m'en faire part en commentaire.
1. Environnement technique utilisé
D'un côté, un serveur Oracle 12.2.0.1 sous OracleLinux que j'appelerai ici "ora.mondomaine.fr" avec une base de données nommée "bd_oracle" et un schéma nommé "schemora". Peu importe si le schéma contient des tables ou pas dans le cadre de ce tutoriel.
De l'autre côté, un serveur MariaDB (sous OpenSuse mais peu importe) que j’appellerai ici "mdb.mondomaine.fr" avec une base de données nommée "bd_maria" et une table nommée "t_source" contenant quelques lignes. Peu importe la structure de la table ; ce n'est pas important dans le cadre de ce tutoriel.
L'utilisateur autorisé à se connecter à la table pour l'interroger sera 'useroracle'@'ora.mondomaine.fr' et son mot de passe "User_ORA" (parce que, évidemment, vous n'accédez pas à vos BDD en root, n'est-ce pas ? ).
Bien entendu, les deux serveurs sont aptes à communiquer l'un avec l'autre.
2. Installation du driver ODBC
On commence par installer, si ce n'est pas déjà fait, le driver "unixODBC" sur le serveur Oracle :
sudo yum install unixODBC unixODBC-devel -y
3. Installation du connecteur ODBC pour MariaDB
Sur le serveur Oracle, il faut installer le connecteur ODBC propre à MariaDB pour que Oracle puisse interroger la BDD MariaDB.
Nota :
Comme je suis sur un serveur sous Oracle Linux, j'ai d'abord essayé d'installer le connecteur ODBC pour MySQL fournit dans la distribution mais je n'ai pas réussi à accéder à MariaDB, malgré la compatibilité de principe existant entre MySQL et MariaDB.
Conformément aux instructions présentes sur le site de MariaDB, pour RedHat et CentOS (puisque Oracle Linux est un clone de RedHat), on télécharge le connecteur dans un répertoire créé pour l'occasion puis on l'installe :
1 2 3 4 5 6 7 8 9 10 11 12 13
| mkdir odbc_package
cd odbc_package
wget https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.7/mariadb-connector-odbc-3.1.7-ga-rhel7-x86_64.tar.gz
tar -xvzf mariadb-connector-odbc-3.1.7-ga-rhel7-x86_64.tar.gz
sudo install lib64/libmaodbc.so /usr/lib64/
sudo install -d /usr/lib64/mariadb/
sudo install -d /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/auth_gssapi_client.so /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/caching_sha2_password.so /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/client_ed25519.so /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/dialog.so /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/mysql_clear_password.so /usr/lib64/mariadb/plugin/
sudo install lib64/mariadb/plugin/sha256_password.so /usr/lib64/mariadb/plugin/ |
4. Création de la source de données
On peut suivre maintenant les instructions de la page "Creating a Data Source with MariaDB Connector/ODBC" pour configurer le driver unixODBC afin qu'il puisse communiquer avec MariaDB. Commençons par créer, avec l'éditeur de notre choix, un fichier "MariaDB_odbc_driver_template.ini" décrivant le connecteur ODBC de MariaDB et le chemin du fichier à utiliser pour le driver :
1 2 3
| [MariaDB ODBC 3.0 Driver]
Description = MariaDB Connector/ODBC v.3.0
Driver = /usr/lib64/libmaodbc.so |
Puis installons cette configuration dans le fichier de configuration de unixODBC : /etc/odbcinst.ini
sudo odbcinst -i -d -f MariaDB_odbc_driver_template.ini
L'installation doit donner un message de ce genre :
odbcinst: Driver installed. Usage count increased to 1.
Target directory is /etc
Si vous vérifiez le contenu du fichier "/etc/odbcinst.ini", vous y trouverez à la fin le contenu de notre fichier "MariaDB_odbc_driver_template.ini".
5. Création d'un Data Source Name (DSN)
Nous allons maintenant créer la définition de la source de données MariaDB qui sera interrogée par Oracle. Vous devrez bien sûr répéter cette opération pour chaque source de données à interroger.
Puisque j'ai nommé la base de données à interroger "bd_maria", nous créons un fichier "bd_maria_odbc.ini". Ce nom étant utilisé plus tard dans la configuration, si vous le changez, tenez-en compte par la suite !
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [ODBC Data Sources]
bd_maria=bd_maria schema data source
[bd_maria]
Driver = /usr/lib64/libmaodbc.so
Description = ODBC for MariaDB
SERVER = mdb.mondomaine.fr
PORT = 3306
USER = useroracle
Password = User_ORA
charset = utf8mb4
OPTION = 3
Database = bd_maria
SOCKET = |
Notas :
J'ai dû remplacer le nom du serveur MariaDB par son IP et, côté MariaDB, j'ai dû changer l'utilisateur en 'useroracle'@'<ip du serveur Oracle>'.
Si votre table a un autre charset, vous pouvez le modifier. De toute manière, vous verrez par la suite que j'ai dû aussi faire une conversion explicite dans mes requêtes Oracle pour les colonnes de texte.
Installons ce fichier dans la configuration globale /etc/odbc.ini :
sudo odbcinst -i -s -l -f bd_maria_odbc.ini
Puis vérifions qu'on peut se connecter à la base de données MariaDB depuis le serveur Oracle avec l'utilitaire isql :
Vous devriez obtenir ceci :
1 2 3 4 5 6 7 8 9
| +---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> |
Et vous pouvez directement lancer des requêtes sur le serveur MariaDB :
1 2 3 4 5 6 7 8 9 10
| SQL> use bd_maria;
SQLRowCount returns 0
SQL> select count(*) from t_source;
+---------------------+
| count(*) |
+---------------------+
| 5 |
+---------------------+
SQLRowCount returns 1
1 rows fetched |
Pour revenir à la console Linux, quittez :
6. Configuration du processus d'écoute Oracle
La configuration ODBC étant terminée, passons à la configuration d'Oracle Database (rappel : la version d'Oracle utilisée est la 12.2.0.1).
Dans le fichier listener.ora, ajoutons un SID pour notre source de données ODBC :
1 2
| cd $ORACLE_HOME/network/admin
vi listener.ora |
Voici le SID à ajouter pour l'exemple de ce tutoriel. Je lui donne le nom "sid_db_maria". Chaque Source de données ODBC doit avoir le sien et c'est le seul paramètre de cette configuration qui change :
<votre ou vos autre(s) SID>
(SID_DESC =
(SID_NAME = sid_db_maria)
(ORACLE_HOME = /produits/oracle/products/12.2.0.1/db_1)
(PROGRAM = dg4odbc)
(ENV = LD_LIBRARY_PATH=/usr/lib64:/produits/oracle/products/12.2.0.1/db_1/lib)
)
7. Création de la passerelle pour ODBC
Afin que Oracle puisse utiliser le DSN défini au chapitre 5, il faut maintenant créer une passerelle pour le service hétérogène ODBC (heterogeneous service : hs) dédié à notre source de données. Il faut donc créer un fichier de paramètres par source de données dans le répertoire $ORACLE_HOME/hs/admin et dont le nom est de la forme : init<SID>.ora. Dans notre cas, ce sera donc le fichier "initsid_db_maria.ora" :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # HS init parameters
#
HS_FDS_CONNECT_INFO = sid_db_maria
HS_FDS_TRACE_LEVEL = DEBUG
HS_TRACE_FILE_NAME = /var/log/odbctrace.log
HS_FDS_SHAREABLE_NAME = /usr/lib64/libmaodbc.so
HS_NLS_NCHAR=UTF8
#
# ODBC specific environment variables
#
set ODBCINI=/home/oracle/pefodbc.ini
set LD_LIBRARY_PATH=/usr/lib64
#
# Environment variables required for the non-Oracle system
#
#set <envvar>=<value>
set HOME=/home/oracle |
8. Configuration du nom de service réseau Oracle
Ajoutons maintenant une entrée dans le fichier $ORACLE_HOME/network/admin/tnsnames.ora :
Voici l'entrée à ajouter :
sid_db_maria =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = ora.mondomaine.fr)
(PORT = 1521)
)
)
(CONNECT_DATA =
(SID = sid_db_maria)
)
(HS = OK)
)
9. Création du lien de base de données (DATABASE LINK)
Nous en avons terminé avec les fichiers de configuration. Dernière étape avant d'interroger notre source de données MariaDB à partir d'Oracle : créer dans la base de données Oracle un lien vers notre source.
J'utilise ici le programme sqlplus mais vous pouvez le faire avec Sql Developer. Je crée un DATABASE LINK public mais vous pouvez le rendre spécifique à un schéma de votre BDD. Je vous renvoie à la documentation d'Oracle pour de plus amples possibilités sur cette création.
Entrons d'abord dans sqlplus :
Puis exécutons cette requête SQL :
CREATE PUBLIC DATABASE LINK <nom du database link> connect to "<user MariaDB>" identified by "<mdp du user MariaDB>" using 'nom du dsn';
C'est à dire pour notre exemple (je nomme le database link "dbl_bd_maria") :
CREATE PUBLIC DATABASE LINK dbl_bd_maria connect to "useroracle" identified by "User_ORA" using 'bd_maria';
Et nous pouvons maintenant interroger notre table MariaDB comme nous l'avions fait tout à l'heure avec isql :
1 2 3 4
| SELECT COUNT(*) FROM "t_source"@dbl_bd_maria;
COUNT(*)
-----------
5 |
10. Quelques subtilités
1) Nommage des objets MariaDB dans les requêtes Oracle.
Vous aurez peut-être remarqué que, dans la dernière requête ci-dessus, j'ai mis le nom de la table entre guillemets. En effet, Oracle met systématiquement les requêtes en lettres capitales. Si les tables, colonnes et autres objets de la bdd MariaDB sont écrits en minuscules, alors il faut mettre ces noms entre guillemets dans les requêtes côté Oracle afin qu'il n'essaie pas d'interroger une table nommée T_SOURCE qui n'existe pas.
2) Transtypage
Bien que ma table soit en utf8mb4 dans MariaDB et que Oracle ait un characterset en principe compatible (AL16UTF16) si j'ai bien compris la doc Oracle à ce sujet, j'ai rencontré des soucis lors de la lecture des caractères accentués et spéciaux. Jai donc dû procéder à une conversion explicite dans mes requêtes Oracle :
SELECT CONVERT("ma_colonne", 'WE8ISO8859P1', 'AL32UTF8') ma_colonne FROM "t_source"@dbl_bd_maria;
3) Taille des colonnes lues lors d'un import
J'ai mis en oeuvre cette technique du DATABASE LINK pour importer des données issues d'une vue MariaDB dans une table Oracle à l'aide d'une procédure Oracle contenant une requête MERGE. Alors que les largeurs des colonnes de texte soient identiques dans la source et la cible, Oracle calculait une longueur de données supérieure au nombre de caractères de la table source. J'ai dû transformer mes colonnes texte côté Oracle de VARCHAR2(<n> BYTE) en VARCHAR2(<n> CHAR) et j'ai dû TRIMer les colonnes interrogées :
SELECT CONVERT(TRIM("ma_colonne"), 'WE8ISO8859P1', 'AL32UTF8') ma_colonne FROM "t_source"@dbl_bd_maria;