Notes de laboratoire de SGBD 3e

Transcription

Notes de laboratoire de SGBD 3e
Notes de laboratoire
Version du 12 septembre 2016 11:42
UE Techniques Avancées de Gestion des données
AA Organisation et exploitation des données 4
3ème Bachelier en Informatique de Gestion
Laurence Herbiet <[email protected]>
Ludovic Kuty <[email protected]>
2015 – 2016
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
2
Table des matières
1 Ressources
5
2 Base de données Oracle
2.1 Setup de base . . . . . . . . . . . . .
2.2 Accès SQL . . . . . . . . . . . . . . .
2.3 Accès SSH . . . . . . . . . . . . . . .
2.4 Setup pour utiliser les objets BFILE
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
8
9
3 MongoDB
3.1 Installation et configuration . . . . . . . . .
3.1.1 Windows . . . . . . . . . . . . . . .
3.1.2 Linux . . . . . . . . . . . . . . . . .
3.1.3 OS X . . . . . . . . . . . . . . . . .
3.2 Administration et interrogation de la BD .
3.3 L’interrogation des données . . . . . . . . .
3.3.1 Exemple : le titre du film 100 . . . .
3.3.2 Exemple : les films et leur cote . . .
3.3.3 Exemple : tous les films avec un titre
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
donné
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
12
12
13
16
16
17
19
21
22
4 Réplication
4.1 Database links . . . . . .
4.2 Synonymes . . . . . . . .
4.3 Scheduling . . . . . . . . .
4.4 Techniques de réplication
4.5 Références . . . . . . . . .
5 En
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
25
28
28
29
29
vrac
Multitenant : CDB et PDB
Les séquences . . . . . . . .
Les transactions . . . . . . .
Comment réaliser des logs ?
Les objets DIRECTORY . .
Les objets BFILE . . . . . .
Le package UTL_FILE . .
Les objets BLOB . . . . . .
Les tables externes . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
31
32
32
33
33
34
34
34
35
3
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
4
Chapitre 1
Ressources
Le PDF des note de cours est disponible à https://cours.khi.be/sgbd3/.
• La documentation de tous les produits Oracle dont leurs serveurs de base de données et Java est
disponible à http://docs.oracle.com/.
• La documentation de leurs serveurs de base de données est disponible à http://docs.oracle.com/en/
database/.
• Oracle Database 12c Release 1
http://docs.oracle.com/database/121/nav/portal_booklist.htm
• PL/SQL Language Reference
http://docs.oracle.com/database/121/LNPLS/toc.htm
• PL/SQL Packages and Types Reference
http://docs.oracle.com/database/121/ARPLS/toc.htm
• SQL Language Reference
http://docs.oracle.com/database/121/SQLRF/toc.htm
• Administrator’s Guide
http://docs.oracle.com/database/121/ADMIN/toc.htm
• Reference. On peut trouver les vues du dictionnaire de données et les limites de la BD.
http://docs.oracle.com/database/121/REFRN/toc.htm.
• Catalog Views / Data Dictionary Views
http://docs.oracle.com/cd/E11882_01/nav/catalog_views.htm.
• SecureFiles and Large Objects Developer’s Guide
http://docs.oracle.com/database/121/ADLOB/toc.htm.
• Utilities
http://docs.oracle.com/database/121/SUTIL/toc.htm.
• Data Warehousing Guide
http://docs.oracle.com/database/121/DWHSG/toc.htm
5
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
6
Chapitre 2
Base de données Oracle
2.1 Setup de base
Nous allons utiliser une base de données Oracle 12cR1 sous la forme d’une machine virtuelle (VM) de type
VirtualBox (Database Virtual Box Appliance / Virtual Machine) mise à disposition par Oracle dans le cadre
de son ”Oracle Technology Network Developer Day”1 .
Il est nécessaire d’installer VirtualBox sur votre machine. Celui-ci peut coexister avec les produits de VMWare. Concrètement vous allez prendre une image nommée DeveloperDaysVM2016-06-02_13.ova de 7.8GB
dont le checksum MD5 est 6ef33e2bef59fbe6d482673ee6f82f66. Nous tiendrons des sticks USB à votre disposition.
Les étapes à réaliser pour ajouter la VM à Virtual Box sont les suivantes :
1. Importez la VM en choisissant File / Import Appliance pour lancer le wizard d’importation.
2. Choisissez votre fichier ova.
3. Démarrez le processus d’importation.
C’est une bonne idée de modifier le port local correspondant à SSH de 22 en par exemple 22222 pour éviter
tout conflit avec un serveur SSH sur votre machine locale. Les autres ports ne sont a priori pas utilisé
localement. Allez dans Virtual Box, menu Machine/Settings (ou bouton Settings), onglet Network, Adapter
1, partie Advanced, Port Forwarding, et vérifiez que vous avez au moins les règles ci-dessous en adaptant le
port local (Host Port) de 22 en 22222 :
• sqlnet – TCP – (vide) – 1521 – (vide) – 1521
• ssh – TCP – (vide) – 22222 – (vide) – 22
Par défaut, n’importe qui peut se connecter aux ports de votre machine. On peut rendre les règles de port
forwarding plus fines en précisant l’IP d’écoute qui plutôt que d’être l’IP publique 0.0.0.0 peut être votre
IP privée 127.0.0.1. Il suffit alors de remplir les cellules vierges dans la colonne ”Host IP” par 127.0.0.1.
Les utilisateurs Unix root et oracle sur la VM ont tous deux le mot de passe oracle. C’est également le
mot de passe de l’utilisateur SYS de la BD.
On vous conseille de travailler à partir de votre machine hôte sur votre BD.
2.2 Accès SQL
Nous vous invitons à lire la section 5.1, page 31 avant de lire cette section.
1
http://www.oracle.com/technetwork/database/enterprise-edition/databaseappdev-vm-161299.html
7
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
L’identifiant d’instance Oracle (SID) est orcl12c ainsi que le nom du service qui correspond au CDB alors
que le nom du service identifiant le PDB que nous utiliserons est orcl.
La création des utilisateurs (des schémas) se fera dans le PDB orcl ainsi que tous les développements liés
au cours. Les informations de connexion pour SYS sont les suivantes :
• Username : SYS
• MDP : oracle
• Role : SYSDBA
• Hostname : 127.0.0.1
• Port : 1521
• Service name : orcl
Pour se connecter au CDB, on remplace simplement le ”service name” par orcl12c.
Avec SQL*Plus, on pourra utiliser un fichier tnsnames.ora ou indiquer la chaîne de connexion (Easy Connect)
comme nous l’avons fait ci-dessous. La commande rlwrap permet d’ajouter les déplacements avec les flèches
et l’historisation sous SQL*Plus ce qui rend son utilisation plus agréable.
Connexion au PDB
$ rlwrap sqlplus sys/oracle@localhost:1521/orcl as sysdba
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
sys@ORCL >
Connexion au CDB
$ rlwrap sqlplus sys/oracle@localhost:1521/orcl12c as sysdba
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
sys@ORCL12C >
2.3 Accès SSH
Nous avons accès par SSH et SFTP (FTP sur SSH) à notre machine. Nous pouvons nous simplifier la vie
en permettant de se connecter sans mot de passe à l’aide d’une paire de clés RSA privée/publique.
Utilisez PuTTY et PuTTYgen sous Windows ou ssh-keygen sous Unix (Linux, OS X) pour générer une
paire de clés ou vous en avez déjà une vous pouvez l’utiliser. Copiez la clé publique id_rsa.pub générée
dans le fichier /home/oracle/.ssh/authorized_keys et le tour est joué. Les étapes détaillées sont indiquées
ci-dessous.
Clé publique sur l’ordinateur hôte
$ pwd
/Users/ludo/.ssh
$ cat id_rsa.pub
ssh-rsa AAAA...iub4RrM= ludo@mac
Etapes de configuration la VM
[oracle@vbgeneric ~]$ pwd
/home/oracle
12 septembre 2016 11:42
8
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
[oracle@vbgeneric ~]$ mkdir .ssh
[oracle@vbgeneric ~]$ chmod 700 .ssh/
[oracle@vbgeneric ~]$ cd .ssh/
[oracle@vbgeneric .ssh]$ vim authorized_keys
[oracle@vbgeneric .ssh]$ cat authorized_keys
ssh-rsa AAAA...iub4RrM= ludo@mac
[oracle@vbgeneric .ssh]$ chmod 600 authorized_keys
2.4 Setup pour utiliser les objets BFILE
En tant qu’utilisateur oracle, créez un répertoire bfile pour pouvoir utiliser les objets BFILE.
mkdir /home/oracle/bfile
12 septembre 2016 11:42
9
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
10
Chapitre 3
MongoDB
MongoDB1 est un système de gestion de bases de données non relationnelle orientée documents qui fait
partie de la catégorie des BDs dites NoSQL2 comme CouchDB. Elle a été conçue pour être performante,
disponible et scalable.
Une base de données MongoDB contient des collections. Chaque collection contient des documents. Une
collection est l’équivalent d’une table dans le monde relationnel et un document est l’équivalent d’un tuple
avec cependant deux différences importantes :
• Il n’y a pas de schéma. Chaque document peut avoir une structure différente de celle des autres
documents de la collection.
• Un document peut contenir des tableaux et d’autres documents ce qui permet de représenter aisément
des hiérarchies complexes.
Un document est un ensemble ordonné de paires clé / valeur. En Javascript on parle de propriétés ayant un
nom et une valeur et dans la documentation de MongoDB on parle de paires de champ / valeur (field-andvalue pairs). Nous utiliserons donc les termes ”clé”, ”champ” et ”nom de propriété” comme synonymes.
La représentation interne des documents est réalisée dans le format BSON3 qui est un format binaire. Les
documents ont une structure à la JSON et BSON en est une sérialisation binaire. La représentation externe
varie selon le langage de programmation utilisé mais on rencontre typiquement celle de Javascript où un
document correspond à un objet JS contenant des propriétés. D’ailleurs, le shell mongo est un interpréteur
JS ce qui fait que les résultat des requêtes sont des données JS. En Java par exemple, on utilisera une classe
spécifique du driver comme Document ou BsonDocument.
Par conséquent, nous sommes particulièrement intéressés par la correspondance (mapping) entre les types
de données de BSON et les types de données du langage que nous avons choisi d’utiliser. Cet intérêt est
récurrent en informatique puisqu’on doit souvent faire interagir des systèmes dont les types de données
diffèrent. Pensez par exemple à SQL et Java par l’intermédiaire de JDBC.
Nous vous invitons à lire la section ”Getting Started” de l’édition ”mongo Shell Edition” de la documentation4 qui débute par une introduction à MongoDB. Nous utiliserons une API pour interagir avec la base de
données ou du Javascript dans le shell mongo ce qui implique que nous ne serons pas directement confrontés
à du BSON et à son encodage/décodage binaire. Toutes les données textuelles (les chaînes de caractères)
sont encodées en UTF-8.
Pour clarifier les choses, nous allons faire des tests sur une collection contenant des films appelée movies et
qui est disponible sur le site web sous la forme du fichier movies_mongo.rar. Notez que ces données ne seront
1
http://www.mongodb.org/
http://en.wikipedia.org/wiki/NoSQL
3
http://bsonspec.org/
4
https://docs.mongodb.com/getting-started/shell/
2
11
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
pas utilisées directement dans le cadre du développement des fonctionnalité puisque nous utiliserons une
table externe.
Le nom de collection complètement qualifié est movies.movies qui est la concaténation du nom de la base
de données (movies) avec le nom de la collection (movies) est appelé un espace de noms (namespace) ou NS
pour faire court.
3.1 Installation et configuration
MongoDB est disponible sous Linux, Windows et OS X. Les versions 3.2.x de la Community Edition sont
supportées dans le cadre du cours et plus précisément la 3.2.9. Nous vous conseillons de lire la procédure
relative à l’installation5 indiquée dans la documentation concernant votre OS.
Les sections ci-dessous vous indiquent comment installer MongoDB sous Windows, Linux (Ubuntu) et OS
X. Ensuite nous allons tester notre collection de films. Cette étape de test est commune quelle que soit l’OS
que vous utilisez.
3.1.1 Windows
L’installation a été testée sous Windows 10 et Windows 7. Installez d’abord le hotfix6 si vous avez un
Windows 7. Celle-ci demande quelques opérations manuelles.
1. Téléchargez et décompressez le fichier zip qui correspond à votre version de Windows après avoir cliqué
sur ”All Version Binaries”. Vous pouvez le prendre avec le support SSL. Ce sera probablement une
variante de mongodb-win32-x86_64-2008plus-ssl-v3.2-latest.zip. Inutile d’utiliser le .msi étant donné
que, à part la création du service Windows, l’installation par msi ne vous fournit rien de plus qu’une
copie des fichiers dans un répertoire.
2. Pour simplifier les chemins, nous avons choisi d’installer MongoDB dans le répertoire c:\mongodb. Si
la décompression a produit un autre nom de répertoire se trouvant à un autre endroit nous vous
suggérons de le renommer et de le déplacer.
3. Cette étape est optionnelle mais vous facilitera la vie en rendant accessible les commandes MongoDB depuis n’importe quel répertoire dans le shell. Mettez à jour la variable d’environnement système Path en allant sur Computer / clic-droit / Properties / Advanced system settings / Advanced
/ Environment Variables... / System variables / Path et ajoutez c:\mongodb\bin.
4. Créez un répertoire data dans le répertoire de MongoDB, c’est-à-dire dans notre cas c:\mongodb\data.
Celui-ci contiendra nos bases de données.
5. Téléchargez le fichier rar nommé movies_mongo.rar contenant la BD movies sur le site web du cours.
6. Décompressez l’archive dans le répertoire c:\mongodb\data avec un ”extract here”. Dans ce répertoire
vous devriez avoir des fichiers nommés movies.xxx où xxx est remplacé par des nombres (0, 1, …) ou
ns.
7. Créez un fichier texte C:\mongodb\mongod.conf dans lequel vous allez indiquer les options de configuration se trouvant ci-dessous.
8. Démarrez MongoDB en lançant un shell de commande Windows, en vous plaçant dans le répertoire
c:\mongodb\bin si le Path n’a pas été mis à jour et en écrivant mongod --config C:\mongodb\mongod.
conf. Vous remarquerez que MongoDB installe un certain nombre de fichiers et répertoires dans le
répertoire data.
9. Lorsque vous avez fini d’utiliser le serveur, vous pouvez l’arrêter simplement avec un CTRL+C.
5
6
https://docs.mongodb.com/manual/administration/install-community/
http://support.microsoft.com/kb/2731284
12 septembre 2016 11:42
12
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Exemple de fichier de configuration YAML
systemLog:
destination: file
path: C:\mongodb\mongo.log
logAppend: true
storage:
dbPath: C:\mongodb\data
engine: mmapv1
net:
bindIp: 127.0.0.1
Le choix par défaut de l’engine est WiredTiger7 qui diffère de l’engine MMAPv18 utilisé par la BD movies.
C’est pourquoi on force l’engine à utiliser grâce à l’option storage.engine.
3.1.2 Linux
Dans un premier temps, si la machine Linux est une VM nous allons nous faciliter la vie en choisissant un
mot de passe simple pour root et en lui permetant de se connecter par mot de passe. Bien entendu, on peut
également placer notre clé publique SSH dans authorized_keys de manière à ne plus devoir entrer de mot
de passe. Il est d’ailleurs plus sécurisé de ne faire que la procédure d’accès par clé publique plutôt que de
donner un accès avec un mot de passe par SSH. L’idéal étant de ne permettre l’accès par mot de passe que
par la console et de plus avec un mot de passe assez complexe.
Mot de passe simple et SSH.
root@test -vm:~# passwd root
root@test -vm:~# apt-get install openssh -server vim
root@test -vm:~# vim /etc/ssh/sshd_config
On modifie la ligne pour avoir: PermitRootLogin yes
root@test -vm:~# service ssh reload
Installation de la clé publique pour test et root.
test@test -vm:~$ mkdir .ssh
test@test -vm:~$ chmod 700 .ssh
test@test -vm:~$ cd .ssh/
test@test -vm:~/.ssh$ vim authorized_keys
test@test -vm:~/.ssh$ chmod 600 authorized_keys
test@test -vm:~/.ssh$ cat authorized_keys
ssh-rsa AAAA...Dziub4RrM= ludo@mac
root@test -vm:~# mkdir .ssh
root@test -vm:~# chmod 700 .ssh/
root@test -vm:~# cd .ssh/
root@test -vm:~/.ssh# vim authorized_keys
root@test -vm:~/.ssh# chmod 600 authorized_keys
root@test -vm:~/.ssh# cat authorized_keys
ssh-rsa AAAA...Dziub4RrM= ludo@mac
Vous avez trois choix : compiler à partir des sources, télécharger un binaire précompilé ou trouver MongoDB
comme un package de votre distribution. Nous avons choisi avec Ubuntu 16.04.1 LTS de télécharger un
7
8
https://docs.mongodb.com/manual/core/wiredtiger/
https://docs.mongodb.com/manual/core/mmapv1/
12 septembre 2016 11:42
13
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
package binaire pour disposer d’une version récente de MongoDB sans être obligé de tout compiler dont le
nom est mongodb-linux-x86_64-ubuntu1604-3.2.9.tgz. Nous allons placer MongoDB dans /opt et octroyer
à l’utilisateur test la propriété du répertoire. On aurait même pu laisser MongoDB dans le répertoire
utilisateur de test.
Pour désactiver les Transparent Huge Pages (THP) et éviter deux warnings, vous pouvez utiliser la solution proposée à http://askubuntu.com/a/820116/94721. Le problème est décrit dans la documentation de
MongoDB à https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/.
Installation de MongoDB.
scp mongodb -linux-x86_64 -ubuntu1604 -3.2.9.tgz [email protected]:/home/test
root@test -vm:~# cd
root@test -vm:/opt#
root@test -vm:/opt#
root@test -vm:/opt#
root@test -vm:/opt#
root@test -vm:/opt#
/opt
mv /home/test/mongodb -linux-x86_64-ubuntu1604 -3.2.9.tgz .
tar xfz mongodb -linux-x86_64 -ubuntu1604 -3.2.9.tgz
rm mongodb -linux-x86_64-ubuntu1604 -3.2.9.tgz
ln -s mongodb -linux-x86_64-ubuntu1604 -3.2.9 mongodb
chown -R test: mongodb -linux-x86_64-ubuntu1604 -3.2.9/
En tant que test, on ajoute le répertoire bin de MongoDB à la variable d’environnement PATH :
test@test -vm:~$ echo 'export PATH=$PATH:/opt/mongodb/bin$'
On crée le fichier de configuration /opt/mongodb/mongod.conf.
Fichier de configuration de MongoDB
test@test -vm:/opt/mongodb$ cat mongod.conf
systemLog:
destination: file
path: /opt/mongodb/mongo.log
logAppend: true
storage:
dbPath: /opt/mongodb/data
engine: mmapv1
net:
bindIp: 0.0.0.0
Le bindIp sur 0.0.0.0 a été fait pour permettre à la machine hôte de se connecter à la VM Linux contenant
MongoDB.
On peut lancer le serveur. Notez qu’au préalable nous avons vidé le contenu du fichier de log pour y voir
plus clair (sans effacer le fichier). On arrête ensuite le serveur avec CTRL+C et on examine le contenu du
répertoire.
Premier démarrage du serveur MongoDB.
test@test -vm:~$ > /opt/mongodb/mongo.log
test@test -vm:~$ mongod --config /opt/mongodb/mongod.conf
^C
test@test -vm:~$ ls -l /opt/mongodb/data
total 1081360
drwxrwxr -x 2 test test
4096 Sep 8 16:56 diagnostic.data
drwxrwxr -x 2 test test
4096 Sep 8 16:56 journal
-rw------- 1 test test 67108864 Sep 8 16:56 local.0
12 septembre 2016 11:42
14
HEPL 2015–2016
-rw------- 1 test test
-rw-r--r-- 1 test test
-rw-rw-r-- 1 test test
Notes de cours de SGBD
16777216 Sep
0 Sep
69 Sep
L. Herbiet & L. Kuty
8 16:56 local.ns
8 16:56 mongod.lock
8 16:20 storage.bson
On peut regarder le contenu du fichier de log dans une autre session SSH pendant que le serveur MongoDB
est en cours d’exécution.
Examination du fichier de log de MongoDB.
test@test -vm:~$ head -n 20 /opt/mongodb/mongo.log
2016-09-08T16:59:00.339+0200 I CONTROL [main] ***** SERVER RESTARTED *****
2016-09-08T16:59:00.344+0200 I CONTROL [initandlisten] MongoDB starting : pid=6974 port←=27017 dbpath=/opt/mongodb/data 64-bit host=test-vm
2016-09-08T16:59:00.344+0200 I CONTROL [initandlisten] db version v3.2.9
...
2016-09-08T16:59:00.344+0200 I CONTROL [initandlisten] options: { config: "/opt/mongodb←/mongod.conf", net: { bindIp: "0.0.0.0" }, storage: { dbPath: "/opt/mongodb/data", ←engine: "mmapv1" }, systemLog: { destination: "file", logAppend: true, path: "/opt/←mongodb/mongo.log" } }
...
On installe ensuite la commande rar pour extraire l’archive contenant les films. Nous allons utiliser l’archive
fournie par RARLAB9 qui produisent WinRAR.
Installation de la commande rar.
test@test -vm:~$ wget http://www.rarlab.com/rar/rarlinux -x64 -5.4.0.tar.gz
test@test -vm:~$ tar xfz rarlinux -x64 -5.4.0.tar.gz
test@test -vm:~$ rm rarlinux -x64 -5.4.0.tar.gz
test@test -vm:~$ mkdir bin
test@test -vm:~$ cd bin
test@test -vm:~/bin$ cp ../rar/rar .
test@test -vm:~/bin$ echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
On suppose que le fichier movies_mongo.rar se trouve dans le répertoire /opt/mongodb/data. On peut l’y
placer à l’aide de SFTP (FileZilla, WinSCP), scp (PuTTY, WinSCP, SSH), …par exemple en faisant
scp movies_mongo.rar [email protected]:/opt/mongodb/data
Regardons le contenu de l’archive pour vérifier qu’aucune arborescence ne sera créée lors de la décompression.
Contenu de l’archive de la BD des films.
test@test -vm:/opt/mongodb/data$ ls -l movies_mongo.rar
-rw-r--r-- 1 test test 112607083 Sep 8 16:18 movies_mongo.rar
test@test -vm:/opt/mongodb/data$ rar vb movies_mongo.rar
movies.0
movies.1
movies.2
movies.3
movies.ns
On arrête le serveur MongoDB avec CTRL+C s’il est démarré et on extrait l’archive. Ensuite on redémarre
le serveur.
En cas de problème, on peut aller regarder le fichier de log de MongoDB situé à /opt/mongodb/mongo.log.
9
http://www.rarlab.com/
12 septembre 2016 11:42
15
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Extraction de l’archive.
test@test -vm:/opt/mongodb/data$ rar x ~/movies.rar
# ls -l
...
-rw------- 1 test test 67108864 Aug 12 22:28 movies.0
-rw------- 1 test test 134217728 Sep 5 12:50 movies.1
-rw------- 1 test test 268435456 Sep 5 13:05 movies.2
-rw------- 1 test test 536870912 Sep 5 13:06 movies.3
-rw------- 1 test test 16777216 Sep 5 13:05 movies.ns
...
Je peux me connecter au serveur MongoDB à partir de machine hôte OS X :
Connexion distante à au serveur MongoDB
$ mongo --host 192.168.130.136
MongoDB shell version: 3.2.9
connecting to: 192.168.130.136:27017/test
3.1.3 OS X
Nous vous conseillons d’installer le package mongodb avec Homebrew10 . Notez que vous aurez besoin d’installer
Xcode grâce à l’App Store avant d’installer Homebrew, y compris les ”Command Line Tools” en exécutant
xcode-select --install.
Vous pouvez suivre les étapes indiquées pour Linux en personnalisant le fichier mongod.conf pour indiquer
où se trouve vos bases de données.
Si vous souhaitez utiliser la configuration par défaut, vous trouverez la ligne à utiliser pour lancer mongod
en écrivant brew info mongodb, ce qui vous donnera également le chemin vers le fichier de configuration, à
savoir:
mongod --config /usr/local/etc/mongod.conf
Le contenu du fichier de configuration est indiqué ci-dessous.
Fichier de configuration par défaut sous OS X.
systemLog:
destination: file
path: /usr/local/var/log/mongodb/mongo.log
logAppend: true
storage:
dbPath: /usr/local/var/mongodb
net:
bindIp: 127.0.0.1
3.2 Administration et interrogation de la BD
On interagit avec la base de données de deux manières que ce soit pour l’administrer ou pour l’utiliser :
10
http://brew.sh/
12 septembre 2016 11:42
16
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
• Soit avec l’outil en ligne de commande appelé mongo11 .
• Soit par programmation à l’aide de ce qu’on appelle un driver. Les drivers officiellement supportés
sont indiqués sur le site de MongoDB12 . Nous effectuerons des tests avec le driver de Java13 .
Le serveur de MongoDB appelé mongod est en écoute sur le port 27017.
Comme indiqué précédemment, le serveur mongod est configuré à l’aide d’un fichier dont on peut personnaliser
l’emplacement à l’aide de l’option --config lors du lancement de celui-ci. Il existe deux formats de fichier :
l’ancien de la version 2.414 qui est toujours utilisable et celui utilisé à partir de la version 2.6 15 au format
YAML.
Celui-ci est localisé à différents endroits selon l’OS. Par exemple, sous OS X on lance le serveur en écrivant
dans un terminal après une installation par défaut avec Homebrew :
mongod --config /usr/local/etc/mongod.conf
Le fichier est localisé à :
• Windows : c:\mongodb\mongod.conf par exemple
• Linux : /etc/mongod.conf
• OS X : /usr/local/etc/mongod.conf avec Homebrew par défaut
3.3 L’interrogation des données
Une BD MongoDB est constituée d’un ensemble de documents, chacun possédant un identifiant _id qui peut
être qualifié de clé primaire si on utilise le jargon des BDs relationnelles. Par défaut, un index est construit
sur ce champ (ou propriété) _id de manière à pouvoir accéder rapidement aux données comme on peut le
voir ci-dessous. Il s’agit d’ailleurs du seul index défini par défaut sur toute collection.
Vous pouvez invoquer la commande mongo avec l’option --host pour spécifier le serveur auquel vous souhaitez
vous connecter.
$ mongo
MongoDB shell version: 3.2.9
connecting to: 192.168.130.136:27017/test
> use movies
switched to db movies
> db.movies.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "movies.movies"
}
]
11
https://docs.mongodb.com/manual/reference/program/mongo/
https://docs.mongodb.com/ecosystem/drivers/
13
https://docs.mongodb.com/ecosystem/drivers/java/
14
https://docs.mongodb.com/v2.4/reference/configuration-options/
15
https://docs.mongodb.com/manual/reference/configuration-options/
12
12 septembre 2016 11:42
17
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
L’interrogation (querying) d’une BD MongoDB se fait à l’aide de ”query documents” qui sont des sortes
de templates de document dans lesquels on précise les valeurs désirées ou les expressions de recherche pour
certains champs.
On peut aussi faire des projections comme en SQL de manière à n’avoir qu’un sous-ensemble des données.
Nous allons utiliser la documentation de référence pour déterminer la syntaxe des différents opérateurs
et commandes. Celle-ci est disponible à https://docs.mongodb.com/manual/reference/ et en particulier les
méthodes du shell mongo à https://docs.mongodb.com/manual/reference/method/. Il est également intéressant
de disposer du glossaire des termes MongoDB à https://docs.mongodb.com/manual/reference/glossary/.
Avant l’exécution des exemples ci-dessous, il est nécessaire de sélectionner la base de données movies à l’aide
de la commande use.
> use movies
switched to db movies
Lorsqu’on désire utiliser un langage de programmation pour accéder à une base de donnée MongoDB, on
utilise un driver pour ce langage. Pour Java, la documentation et le driver lui-même sont disponibles à
https://docs.mongodb.com/ecosystem/drivers/java/. Nous utiliserons le driver version 3.3.
La page d’accueil du driver Java nous mène vers http://mongodb.github.io/mongo-java-driver/ qui permet
de télécharger le jar du driver mongo-java-driver-3.3.0.jar et de consulter la documentation dont les URLs
sont http://mongodb.github.io/mongo-java-driver/3.3/ pour la documentation de référence et http://api.
mongodb.com/java/3.3/ pour la javadoc de l’API. Dans la section ”Getting Started with Java Driver” (Quick
Tour16 ) de la documentation de référence vous avez un exemple de connexion à MongoDB de manière à
obtenir un objet de type com.mongo.MongoDatabase représentant votre base de données.
En java, nous utiliserons toujours le code ci-dessous pour nous connecter à notre base de données. Si vous
utilisez Netbeans, l’idéal est de créer une librairie reprenant l’implémentation, les sources et la documentation
javadoc sous la forme des fichiers mongo-java-driver-3.3.0.jar, mongo-java-driver-3.3.0-sources.jar et
mongo-java-driver-3.3.0-javadoc.jar.
import
import
import
import
import
import
com.mongodb.MongoClient;
com.mongodb.client.MongoCollection;
com.mongodb.client.MongoDatabase;
java.util.logging.Level;
java.util.logging.Logger;
org.bson.Document;
public class MongoDBConnection {
public static void main(String[] args) {
// http://mongodb.github.io/mongo-java-driver/3.3/driver/reference/management/←logging/
Logger mongoLogger = Logger.getLogger("org.mongodb.driver");
mongoLogger.setLevel(Level.SEVERE);
MongoClient mongoClient = new MongoClient("localhost");
MongoDatabase db = mongoClient.getDatabase("movies");
MongoCollection <Document > collection = db.getCollection("movies");
System.out.printf("Size of movies collection is %d\n", collection.count());
}
}
16
http://mongodb.github.io/mongo-java-driver/3.3/driver/getting-started/quick-tour/
12 septembre 2016 11:42
18
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Nous allons également utiliser notre méthode displayDocument pour afficher en détail un document extrait de
la collection. Cette méthode utilise les streams de Java 8 et l’opération forEach avec une lambda expression
(fonction anonyme).
public static void displayDocument(Document doc) {
doc.keySet().stream().forEach(key -> {
Object value = doc.get(key);
System.out.printf("KEY: %s, TYPE: %s, VALUE: %s\n",
key,
value != null ? value.getClass().getName() : "N/A",
value != null ? value.toString() : "null");
});
}
Les exemples sont repris dans le code source disponibles à https://cours.khi.be/sgbd3/labo/MongoDBExamples.
java.
3.3.1 Exemple : le titre du film 100
Nous allons utiliser la méthode find du shell mongo pour trouver le titre du film 100. Le critère de recherche
est un document qualifié de ”query document”. Pour disposer de tous les films, on peut ne pas spécifier
de critère ou alors indiquer un document vide. Remarquez l’utilisation de la méthode de curseur (cursor
method) limit pour limiter le nombre de documents renvoyés par le curseur.
> db.movies.find().count()
300834
> db.movies.find().limit(1)
{ "_id" : 32, ..., "title" : "Cannon Fodder", ... }
Pour trouver le film dont le champ _id vaut 100, on utilise un objet JS contenant uniquement le champ _id
avec la valeur 100.
> db.movies.find({"_id": 100})
{ "_id" : 100, ..., "title" : "Lock, Stock and Two Smoking Barrels", ...}
Pour projeter le résultat sur les champs _id et title, on utilise un second objet JS avec la valeur 1 pour le
champ title. Le champ _id est présent par défaut mais on peut l’exclure du résultat avec la valeur 0.
>
{
>
{
db.movies.find({"_id":
"_id" : 100, "title" :
db.movies.find({"_id":
"title" : "Lock, Stock
100}, {"title": 1})
"Lock, Stock and Two Smoking Barrels" }
100}, {"_id": 0, "title": 1})
and Two Smoking Barrels" }
Bien que cela ne soit pas apparent dans l’exemple ci-dessus, la méthode find renvoie un curseur. Par défaut,
un curseur non assigné à une variable locale est itéré un maximum de 20 fois de manière à afficher les
résultats à l’écran. Si le curseur est assigné à une variable alors la taille du batch est plus importante mais
néanmoins tous les enregistrements ne sont pas retournés en une fois pour peu que ceux-ci excèdent une
certaine taille.
> var c = db.movies.find({"_id": 100}, {"_id": 0, "title": 1})
> c.hasNext()
true
> c.next()
{ "title" : "Lock, Stock and Two Smoking Barrels" }
12 septembre 2016 11:42
19
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
La méthode findOne quant à elle ne renvoie qu’un seul document et non un curseur. Si plusieurs documents
satisfont le critère de recherche alors le premier selon un certain ordre est renvoyé.
> var d = db.movies.findOne({"_id": 100}, {"_id": 0, "title": 1})
> d
{ "title" : "Lock, Stock and Two Smoking Barrels" }
En Java, un document de la base de données est représenté par l’interface org.bson.conversions.Bson que
plusieurs classes implémentent dont la classe org.bson.Document qui peut être utilisée comme une map (java
.util.Map). Lorsqu’on exécute un find, on obtient un objet de type FindIterable<TDocument> qui est itérable
et qui contient nos documents où dans notre cas la variable de type TDocument sera Document. En utilisant la
méthode first on obtient le premier document de la séquence ce qui est très pratique quand il n’y a qu’un
document car on récupère un objet de type Document plutôt qu’un FindIterable.
On crée un ”query document” à l’aide de la classe com.mongodb.client.model.Filters. Pour une utilisation
agréable en Java, on vous invite à importer statiquement toutes ses méthodes statiques ou une partie de
celles-ci avec le mot clé import static. Ainsi pour utiliser un filtre d’égalité, on n’est pas obligé d’écrire
Filters.eq() mais simplement eq().
Une projection est également réalisée avec un document qui est créé à l’aide de la classe com.mongodb.
client.model.Projections. La même remarque que précédemment nous conduit à importer statiquement les
méthodes (statiques) de Projections. Nous sommes intéressés par les méthodes include, exclude, excludeId
et fields.
import static com.mongodb.client.model.Filters.*;
import static com.mongodb.client.model.Projections.*;
...
Document document;
document = movies
.find(eq("_id", 100))
.projection(fields(include("title"), excludeId()))
.first();
displayDocument(document);
Si on n’utilise pas la méthode first alors on récupère un FindIterable et il nécessaire de parcourir la
séquence des documents. Il y a plusieurs façons de procéder :
1. Soit en utilisant un forEach avec un Block (interface MongoIterable).
2. Soit en utilisant un forEach avec Consumer (interface Iterable du JDK).
3. Soit en utilisant la méthode iterator qui nous renvoie un MongoCursor qui hérite de la méthode
forEachRemaining de l’interface Iterator du JDK. On peut passer un Consumer à cette méthode.
4. Soit en convertissant la séquence en un stream (interface Stream du JDK).
Notre but est de pouvoir passer une expression lambda à la méthode en question. Le souci avec les deux
méthodes forEach est qu’elles coexistent toute les deux dans FindIterable et que Java ne parvient pas à
déterminer celle qu’on désire utiliser en indiquant une expression lambda. Par conséquent nous ne pouvons
pas utiliser les mathodes 1 et 2 et nous nous rabattons sur la 3 ème.
FindIterable <Document > documents;
documents = movies
.find(eq("_id", 100))
.projection(fields(include("title"), excludeId()));
documents.iterator().forEachRemaining(doc -> displayDocument(doc));
Ce qui donne :
12 septembre 2016 11:42
20
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
KEY: title, TYPE: java.lang.String, VALUE: Lock, Stock and Two Smoking Barrels
On peut aussi construire les documents de query et de projection manuellement en utilisant directement la
classe Document.
projectionDoc = new Document("title", 1).append("_id", 0);
queryDoc = new Document("_id", 100);
Documentation :
• Méthode de collection find
https://docs.mongodb.com/manual/reference/method/db.collection.find/
• Méthode de collection findOne
https://docs.mongodb.com/manual/reference/method/db.collection.findOne/
• Méthode de curseur limit
https://docs.mongodb.com/manual/reference/method/cursor.limit/#cursor.limit
• Projection
https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
3.3.2 Exemple : les films et leur cote
La cote d’un film est exprimée à l’aide du champ vote_average et du champ vote_count qui permet de
connaître le nombre de votes.
On reçoit un curseur pour accéder aux films dont le vote_average vaut 9.0. Notez que l’accès à la BD n’a
lieu que lorsqu’on désire connaître le nombre de documents accessible avec ce curseur. La première exécution
prend un certain temps étant donné qu’on doit accéder à chaque document pour voir s’il convient. En effet
nous ne disposons pas d’index sur le champ vote_average.
> var c = db.movies.find({"vote_average": 9.0}, {"title": 1})
> c.count()
2409
> c
{ "_id" : 21, "title" : "The Endless Summer" }
...
Type "it" for more
> it
{ "_id" : 2574, "title" : "The Lovers" }
...
Si on désire trouver tous les films ayant une cote supérieure à 9.0 ou dans une autre requête une cote
comprise entre 9.0 et 9.2, on utilisera des sélecteurs de comparaison (comparison query selectors) dans un
document jouant le rôle de valeur de champ (inner document), c’est-à-dire de la forme "name": document où
document est qualifié de document interne (inner document) car il est dans le champ name.
L’évaluation du curseur dans le shell avec limit (ou sans) provoque la ”consommation” suivie de la fermeture
de celui-ci. C’est pourquoi il est nécessaire de faire une nouvelle requête find pour pouvoir réaliser le second
test.
> var c = db.movies.find({"vote_average": {"$gte": 9.0}}, {"title": 1})
> c.count()
9230
> var c = db.movies.find({"vote_average": {"$gte": 9.0, "$lte": 9.2}}, {"title": 1})
12 septembre 2016 11:42
21
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
> c.count()
2473
> c.limit(1)
{ "_id" : 21, "title" : "The Endless Summer" }
> c.forEach(function(d) { print(d.title) })
...
> var c = db.movies.find({"vote_average": {"$gte": 9.0, "$lte": 9.2}}, {"title": 1})
> c.limit(1).forEach(function(d) { print(d.title) })
The Endless Summer
> c.limit(1)
2016-09-12T11:37:32.652+0200 E QUERY
[thread1] Error: query already executed :
queryBson = and(gte("vote_average", 9.0), lte("vote_average", 9.2));
Block<Document > printBlock = (final Document doc) -> {
System.out.println(doc.toJson());
};
start = System.nanoTime();
documents = movies
.find(queryBson)
.sort(ascending("vote_average", "title"))
.projection(fields(include("title", "vote_average"), excludeId()))
.limit(3);
documents.forEach(printBlock);
Documentation :
• Query and Projection Operators
https://docs.mongodb.com/manual/reference/operator/query/
3.3.3 Exemple : tous les films avec un titre donné
Nous pouvons rechercher tous les films ayant un titre donné ou tous les films dont le titre ”matche” une
expression régulière17 à la Perl (PCRE). Ce mécanisme est puissant mais assez lent. Il est également possible
de faire des recherches sur des mots dans du texte à l’aide d’un index mais ce n’est pas aussi puissant que
les expressions régulières. Cfr. le code en commentaire dans le programme Java.
> db.movies.findOne({"title": "The Fellowship of the Ring"}, {"title": 1})
null
> db.movies.findOne({"title": /^.*Fellowship.*Ring$/}, {"title": 1})
{
"_id" : 120,
"title" : "The Lord of the Rings: The Fellowship of the Ring"
}
> db.movies.find({"title": /^.*Fellowship.*Ring$/}, {"title": 1})
{ "_id" : 120, "title" : "The Lord of the Rings: The Fellowship of the Ring" }
queryBson = regex("title", Pattern.compile("^.*Fellowship.*Ring$"));
documents = movies
.find(queryBson)
.projection(fields(include("title"), excludeId()));
17
http://www.regular-expressions.info/
12 septembre 2016 11:42
22
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
documents.forEach(printBlock);
Documentation :
• Opérateur $regex
https://docs.mongodb.com/manual/reference/operator/query/regex/
12 septembre 2016 11:42
23
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
24
Chapitre 4
Réplication
Dans un système d’information distribué utilisant plusieurs bases de données, on gère les données à l’aide
d’un mélange de deux techniques :
• Le partage ou la distribution pure : les données ne sont pas dupliquées.
• La réplication : les données sont copiées.
Dans les deux cas, on utilise des ”database links” (DB links) pour passer d’un schéma à un autre potentiellement sur une autre base de données qui elle-même peut être située sur une autre machine.
4.1 Database links
Un DB link est un objet SQL qui se trouve dans un schéma sur la base de données locale à l’instar de vos
tables. Il permet d’accéder à des objets dans un schéma distant habituellement sur une base de données
distante. On a besoin de deux privilèges pour pouvoir les utiliser :
• CREATE DATABASE LINK sur la base de données locale.
• CREATE SESSION sur la base de données distante.
On crée un DB link à l’aide de l’instruction CREATE DATABASE LINK dont la syntaxe se trouve au listing 4.1.
Le paramètre db link name peut valoir n’importe quoi sauf si le paramètre de base de données GLOBAL_NAMES
vaut true. Les paramètres user et password sont ceux du schéma distant. La chaîne de connexion connect
string est l’alias TNS qui provient du fichier tnsnames.ora sur la base de données locale, pas celle du client
comme votre portable par exemple.
Quelques précisions s’imposent en ce qui concerne le nom du DB link. Si vous spécifiez un nom qui ne
contient pas de point (.), Oracle ajoute implicitement le domaine de la base de données locale, ce qui peut
conduire à un nom de DB link assez indigeste comme nous le verrons. Dans le cas contraire, Oracle laisse le
nom intact.
Un premier exemple de création de DB link est indiqué au listing 4.2. Le nom du DB link est choisi de
manière libre mais étant donné qu’il n’y a pas de point dans le nom, Oracle ajoute le suffixe khi.be. On
Listing 4.1: Syntaxe de création d’un DB link
CREATE DATABASE LINK db link name
CONNECT TO user IDENTIFIED BY password
USING 'connect string';
25
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Listing 4.2: Création et test d’un DB link
CREATE DATABASE LINK whatever CONNECT TO ludo2 IDENTIFIED BY dummy USING 'db1';
Database link created.
LUDO @ db1> SELECT table_name FROM tabs@whatever;
no rows selected
Listing 4.3: Création d’un DB link absolu
LUDO @ db1> CREATE DATABASE LINK whatever.untouched CONNECT TO ludo2 IDENTIFIED BY dummy←USING 'db1';
Database link created.
peut tester le DB links à l’aide de la table DUAL par exemple. L’exemple du listing 4.3 crée un DB link dont
le nom contient un point ce qui fait qu’Oracle ne modifie pas le nom.
On peut se rendre compte du résultat dans le nommage des DB links en interrogeant le dictionnaire de
données comme cela est fait au listing 4.4. On exécute une requête sur la table USER_DB_LINKS qui décrit les
DB links dont l’utilisateur courant est le propriétaire. Elle a le même format que la table ALL_DB_LINKS sans
la colonne OWNER. Celle-ci est décrite à http://docs.oracle.com/cd/E11882_01/server.112/e40402/statviews_
1067.htm#REFRN20050.
A quoi servent les noms globaux et le paramètre GLOBAL_NAMES ? Une base de données distante peut imposer
que les DB links qui pointent vers elle doivent porter comme nom son nom global. Cela permet d’éviter de
créer des DB links qui sont difficiles à utiliser car ils portent des noms farfelus. Avec ce paramètre, si un DB
link s’appelle db1.khi.be c’est qu’il pointe vers la base de données dont le nom est db1.khi.be. Cela rend les
choses plus claires.
Lorsqu’Oracle impose l’utilisation d’un nom global de base de données, il le fait lorsqu’on utilise le DB
link, pas lorsqu’on le crée. S’il y a un problème lié au fait qu’on n’a pas respecté cette contrainte lors de la
création du DB link, ce n’est que plus tard lors de l’utilisation qu’on s’en rendra compte.
Est-ce que les noms globaux sont imposés par Oracle ? Pour vérifier la valeur du paramètre GLOBAL_NAMES,
on interroge la table V$PARAMETER comme indiqué au listing 4.5. Si les noms globaux sont imposés, il est
évident qu’on aura un problème si on désire créer plusieurs DB links vers la même base de données distante
mais vers des schémas différents. En effet, on ne peut pas créer deux DB links différents qui portent le
même nom. Comment peut-on contourner ce problème ? En utilisant un ”connection qualifier” (un suffixe)
pour distinguer entre les DB links vers la même base de données. La création des DB links et les tests de
fonctionnement sont effectués au listing 4.6. On examine le nom des DB links au listing 4.7.
Listing 4.4: Affichage des DB links de l’utilisateur
LUDO @ db1> SELECT db_link , username , host, created FROM user_db_links;
DB_LINK
USERNAME HOST CREATED
---------------------------------------------------WHATEVER.KHI.BE
LUDO2
db1 10-18-2008 18:35:57
WHATEVER.UNTOUCHED LUDO2
db1 10-18-2008 19:40:54
12 septembre 2016 11:42
26
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Listing 4.5: Affichage de la valeur du paramètre GLOBAL_NAMES
SYS> SELECT name, value FROM v$parameter WHERE name = 'global_names ';
Listing 4.6: Création de deux DB link vers la même base de données lorsque GLOBAL_NAMES est vrai
LUDO @ db1> ALTER SESSION SET global_names=true;
Session altered.
LUDO @ db1> SELECT * FROM global_name;
DB1.KHI.BE
LUDO @ db1> CREATE DATABASE LINK db1.khi.be@extra1 CONNECT TO ludo IDENTIFIED BY dummy ←USING 'db1';
Database link created.
LUDO @ db1> CREATE DATABASE LINK db1.khi.be@extra2 CONNECT TO ludo2 IDENTIFIED BY dummy ←USING 'db1';
Database link created.
LUDO @ db1> SELECT table_name FROM [email protected]@extra1;
...
8 rows selected.
LUDO @ db1> SELECT table_name FROM [email protected]@extra2;
no rows selected
Listing 4.7: Affichage des DB links de l’utilisateur
LUDO @ db1> SELECT db_link , username , host, created FROM user_db_links;
DB_LINK
USERNAME HOST CREATED
---------------------------------------------------DB1.KHI.BE@EXTRA1 LUDO
db1 10-18-2008 19:08:45
DB1.KHI.BE@EXTRA2 LUDO2
db1 10-18-2008 19:09:04
12 septembre 2016 11:42
27
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Listing 4.8: Syntaxe de création d’un synonyme
CREATE SYNONYM schema.synonym name
FOR schema.object name@db link name;
Listing 4.9: Exemple de création et d’utilisation de synonyme sans DB link
LUDO @ db1> CREATE OR REPLACE SYNONYM client_prod FOR ludo2.client;
Synonym created.
LUDO @ db1> SELECT * FROM client_prod;
NOM
--------------Albert Einstein
4.2 Synonymes
Un synonyme est un object SQL qui permet de définir un nom alternatif (alias) pour un objet du schéma
comme une table, une vue, une procédure, un package, etc. Ils permettent d’être indépendant des données
(schémas) et de l’endroit où elle se trouve (base de données). On peut les utiliser avec les DB links.
Pour créer un synonyme privé qui n’est utilisable que par le créateur de celui-ci, on a besoin du privilège
CREATE SYNONYM. Pour créer un synonyme public, on a besoin du privilège CREATE PUBLIC SYNONYM.
La syntaxe utilisée est indiquée au listing 4.8. Les paramètres synonym name et object name peuvent être
préfixés par un nom de schéma. Bien entendu il faut disposer des privilèges nécessaires sur le schéma en
question. On peut fournir un nom de DB link en extra.
On peut voir la différence entre l’accès direct à un schéma et l’utilisation d’un DB link sur les exemples
de listings 4.9 et 4.10. Sur l’exemple du listing 4.9 le synonyme fait directement référence à la table CLIENT
du schéma LUDO2. Cela implique que pour que la requête aboutisse, il est nécessaire que l’utilisateur LUDO
dispose du privilège SELECT ON CLIENT. C’est à LUDO2 de lui accorder avec un GRANT. Sur l’exemple du listing
4.10 le synonyme cache l’utilisation d’un DB link ce qui fait qu’un aucun privilège n’est nécessaire étant
donné que la paire nom d’utilisateur / mot de passe a déjà été spécifiée lors de la création du DB link.
4.3 Scheduling
Cfr. notes sur le site Web.
Listing 4.10: Exemple de création et d’utilisation de synonyme avec DB link
LUDO @ db1> CREATE OR REPLACE SYNONYM client_prod FOR [email protected]@extra2;
Synonym created.
LUDO @ db1> SELECT * FROM client_prod;
NOM
--------------Albert Einstein
12 septembre 2016 11:42
28
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
4.4 Techniques de réplication
4.5 Références
DB links
• Oracle Database Reference, Static Data Dictionary Views, http://docs.oracle.com/cd/
E11882_01/server.112/e40402/statviews_part.htm#REFRN002.
12 septembre 2016 11:42
29
HEPL 2015–2016
12 septembre 2016 11:42
Notes de cours de SGBD
L. Herbiet & L. Kuty
30
Chapitre 5
En vrac
5.1 Multitenant : CDB et PDB
La version 12c de Oracle Database a introduit une nouvelle architecture appelée Multitenant permettant
d’utiliser des bases de données virtuelles dans une base de données physique principalement de manière à
limiter les ressources utilisées.
Chaque base de données virtuelle est appelée un ”container” et la base de données physique qui contient les
containers est appelée une ”container database” (CDB). Etant donné que les containers pouvent être insérés
ou retirés d’un CDB, ils sont appelés des ”pluggable databases” (PDB).
Avec notre VM, l’id d’instance (SID) est orcl12c, le nom du service du CDB est orcl12c et le nom du service
du PDB est orcl.
Grâce à cela, plusieurs bases de données (PDB) peuvent être gérées avec une seule instance (ensemble de
processus et de mémoire) plutôt que d’avoir une instance par base de données.
La base de données Oracle physique peut être une BD de type CDB ou non-CDB. On peut le découvrir en
exécutant la requête suivante lorsqu’on est en session en tant que SYS :
sys@ORCL12C > select cdb from v$database;
CDB
--YES
On peut voir les PDBs présents dans notre CDB. Le CON_ID 1 est réservé pour un container spécial appelé
CDB$Root contenant des méta-données et le container PDB$SEED est utilisé comme template pour créer de
nouveaux PDBs.
sys@ORCL12C > select con_id , dbid, name from v$pdbs;
CON_ID
-----2
3
4
DBID
---------1713883526
2549425181
3227050142
NAME
-------PDB$SEED
ORCL
ORDS
On peut d’ailleurs que nous sommes connectés au CDB, en examinant l’identifiant et le nom de contre
connexion.
31
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
rlwrap sqlplus sys/oracle@localhost:1521/orcl12c as sysdba
sys@ORCL12C > show con_name
CON_NAME
-------CDB$ROOT
sys@ORCL12C > show con_id
CON_ID
-----1
Si on se connecte au PDB orcl, on voit la différence :
rlwrap sqlplus sys/oracle@localhost:1521/orcl as sysdba
sys@ORCL > show con_name
CON_NAME
-------ORCL
sys@ORCL > show con_id
CON_ID
-----3
5.2 Les séquences
• Instruction CREATE SEQUENCE dans ”SQL Language Reference”
Une séquence est un objet SQL dont la raison d’être est de pouvoir générer des nombres entiers de manière
robuste dans un environnement transactionnel multi-utilisateur. La séquence a une valeur que l’on peut
interroger à tout instant, une fois que celle-ci a été initialisée.
Elle dispose de deux pseudo-colonnes :
• CURRVAL qui renvoie la valeur courante de la séquence.
• NEXTVAL qui génère et renvoie la valeur suivante de la séquence ou sa valeur initiale lorsqu’elle n’a pas
encore été utilisée.
5.3 Les transactions
• Oracle Database Concepts, chapitre 10 ”Transactions” : hhttp://docs.oracle.com/database/121/CNCPT/
transact.htm
On vous demande d’utiliser les transactions de manière active, c’est-à-dire de choisir précisément l’endroit
dans votre code où faire un COMMIT ou un ROLLBACK et de pouvoir justifier ce choix. Dans cet esprit on
désactivera toujours les COMMIT automatiques (auto-commit) qu’on peut par exemple trouver avec JDBC.
On vous demande également de ne pas disséminer des COMMIT partout pour éviter par exemple de couper
en deux une séquence d’instructions SQL qui appartiennent logiquement à la même transaction et qui
doivent donc toutes être réalisées ensemble (ou aucune ne doit l’être). Il s’agit du A de ACID. Cela est
particulièrement important car un ROLLBACK (explicite ou implicite) aura pour effet de laisser votre base de
12 septembre 2016 11:42
32
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
Listing 5.1: Exemple de procédure autonome
PROCEDURE log (...) IS
PRAGMA AUTONOMOUS_TRANSACTION;
...
BEGIN
...
END;
données dans un état incohérent du point de vue de votre logique applicative. Attention que le ROLLBACK
peut être provoqué implicitement par Oracle en cas d’erreur.
Il s’agit donc d’utiliser intelligemment ces deux instructions coijointement avec vos gestionnaires d’exception.
5.4 Comment réaliser des logs ?
• Pragma AUTONOMOUS_TRANSACTION au chapitre 13 ”Language Elements” de ”PL/SQL Language Reference”.
Il y a deux types de messages qui peuvent être enregistrés dans une table de log : les messages informatifs et
les messages d’erreur. Vous devez veiller à distinguer les deux, soit en utilisant deux tables différentes, soit
en utilisant une colonne aditionnelle discriminante, soit en utilisant une convention comme par exemple un
code d’erreur nul pour les messages d’information.
Votre table de log doit contenir suffisamment d’informations pour que le message loggé soit utile. Par
conséquent, on retrouve généralement la date-heure de l’erreur (éventuellement avec des fractions de secondes), l’endroit où a eu lieu l’erreur (nom de procédure, fonction, package, déclencheur, …), le code
d’erreur utilisateur ou Oracle et le message d’erreur proprement dit contenant un maximum d’informations
et éventuellement une ”call stack trace”. On utilisera typiquement une séquence comme clé primaire.
De manière à centraliser la logique de log des erreurs, il est vivement conseillé d’utiliser une procédure
indépendante pour gérer ces insertions dans la table de log des erreurs. Lorsque la gestion des erreurs est
plus complexe on peut même utiliser un package et par exemple personnaliser les logs pour sauver les
messages dans un fichier sur disque et/ou à l’écran en plus du log dans une table.
Il est indispensable que la procédure responsable de l’insertion du message dans la table, c’est-à-dire celle
qui contient l’instruction INSERT, soit une procédure autonome, c’est-à-dire telle que l’exécution de la procédure provoque la création d’une nouvelle transaction indépendante de la transaction principale en cours au
moment de l’appel de la procédure. De cette manière tout COMMIT ou ROLLBACK présent dans la procédure de
log n’aura aucun effet sur la transaction principale qui a justement provoqué l’appel de la procédure de log
vraisemblablement à cause d’une erreur. Lorsque la procédure se termine, la transaction principale reprend
là où elle avait été suspendue.
On marque une procédure comme autonome en utilisant le PRAGMA (directive de compilation) AUTONOMOUS_TRANSACTION qu’on écrit dans la partie déclarative de la procédure comme indiqué au listing 5.1.
Remarquez que ce pragma peut s’utiliser également dans des fonctions et à d’autres endroits moins habituels.
5.5 Les objets DIRECTORY
Références :
12 septembre 2016 11:42
33
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
• Instruction GRANT dans la ”SQL Language Reference” et la table 18-1 qui liste les privilèges dont CREATE
ANY DIRECTORY.
• Instruction CREATE DIRECTORY dans la ”SQL Language Reference”
• Les vues ALL_DIRECTORIES (describes all directories accessible to the current user) et USER_TAB_PRIVS
(describes the object grants for which the current user is the object owner, grantor, or grantee).
Voici un extrait de la documentation concernant l’instruction CREATE DIRECTORY.
You must have the CREATE ANY DIRECTORY system privilege to create directories.
When you create a directory, you are automatically granted the READ, WRITE, and EXECUTE
object privileges on the directory, and you can grant these privileges to other users and roles.
The DBA can also grant these privileges to other users and roles.
WRITE privileges on a directory are useful in connection with external tables. They let the
grantee determine whether the external table agent can write a log file or a bad file to the
directory.
For file storage, you must also create a corresponding operating system directory, (...). Your
system or database administrator must ensure that the operating system directory has the correct
read and write permissions for Oracle Database processes.
Privileges granted for the directory are created independently of the permissions defined for
the operating system directory, and the two may or may not correspond exactly.
5.6 Les objets BFILE
• Chapitre 21 ”LOB APIs for BFILE Operations” dans le ”SecureFiles and Large Objects Developer’s
Guide”.
• Fonction BFILENAME dans la ”SQL Language Reference” pour créer un BFILE locator.
5.7 Le package UTL_FILE
• Package UTL_FILE dans ”PL/SQL Packages and Types Reference”.
Voir extrait de la documentation de Oracle ci-dessous.
With the UTL_FILE package, PL/SQL programs can read and write operating system text
files. UTL_FILE provides a restricted version of operating system stream file I/O.
5.8 Les objets BLOB
• SecureFiles and Large Objects Developer’s Guide.
• Package DBMS_LOB dans ”PL/SQL Packages and Types Reference”.
Voir extrait de la documentation de Oracle ci-dessous.
The BLOB data type stores unstructured binary large objects. BLOB objects can be thought
of as bitstreams with no character set semantics. BLOB objects can store binary data up to
(4 gigabytes -1) * (the value of the CHUNK parameter of LOB storage). If the tablespaces in
your database are of standard block size, and if you have used the default value of the CHUNK
parameter of LOB storage when creating a LOB column, then this is equivalent to (4 gigabytes
- 1) * (database block size).
12 septembre 2016 11:42
34
HEPL 2015–2016
Notes de cours de SGBD
L. Herbiet & L. Kuty
BLOB objects have full transactional support. Changes made through SQL, the DBMS_LOB
package, or Oracle Call Interface (OCI) participate fully in the transaction. BLOB value manipulations can be committed and rolled back. However, you cannot save a BLOB locator in a
PL/SQL or OCI variable in one transaction and then use it in another transaction or session.
5.9 Les tables externes
• Partie III ”External Tables” de ”Utilities” et plus particulièrement les chapitres 13 ”External Tables
Concepts” et 14 ”The ORACLE_LOADER Access Driver”.
• Instruction CREATE TABLE dans ”SQL Language Reference” et en particulier les physical_properties
dans lesquelles on retrouve le ORGANIZATION EXTERNAL avec son external_table_clause.
12 septembre 2016 11:42
35

Documents pareils