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 :
Code bash : | Sélectionner tout |
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 :
Code bash : | Sélectionner tout |
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 :
Code ini : | Sélectionner tout |
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
Code bash : | Sélectionner tout |
sudo odbcinst -i -d -f MariaDB_odbc_driver_template.ini
odbcinst: Driver installed. Usage count increased to 1.
Target directory is /etc
Target directory is /etc
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 !
Code ini : | Sélectionner tout |
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 = |
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 :
Code bash : | Sélectionner tout |
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 :
Code bash : | Sélectionner tout |
isql bd_maria
Code bash : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> |
Code : | Sélectionner tout |
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 |
Code : | Sélectionner tout |
SQL>quit
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 :
Code bash : | Sélectionner tout |
1 2 | cd $ORACLE_HOME/network/admin vi listener.ora |
<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)
)
(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)
)
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" :
Code ini : | Sélectionner tout |
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 :
Code bash : | Sélectionner tout |
vi tnsnames.ora
sid_db_maria =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = ora.mondomaine.fr)
(PORT = 1521)
)
)
(CONNECT_DATA =
(SID = sid_db_maria)
)
(HS = OK)
)
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = ora.mondomaine.fr)
(PORT = 1521)
)
)
(CONNECT_DATA =
(SID = sid_db_maria)
)
(HS = OK)
)
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 :
Code bash : | Sélectionner tout |
sqlplus / as sysdba
Code SQL : | Sélectionner tout |
CREATE PUBLIC DATABASE LINK <nom du database link> connect to "<user MariaDB>" identified by "<mdp du user MariaDB>" using 'nom du dsn';
Code SQL : | Sélectionner tout |
CREATE PUBLIC DATABASE LINK dbl_bd_maria connect to "useroracle" identified by "User_ORA" using 'bd_maria';
Code SQL : | Sélectionner tout |
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 :
Code SQL : | Sélectionner tout |
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 :
Code SQL : | Sélectionner tout |
SELECT CONVERT(TRIM("ma_colonne"), 'WE8ISO8859P1', 'AL32UTF8') ma_colonne FROM "t_source"@dbl_bd_maria;