INFO 2014 Fichiers et base de données Philippe Fournier-Viger Département d’informatique, U.de Moncton Bureau D216, philippe.fournier-viger@umoncton.ca
Transactions 26 avril (à vérifier)
LES TRANSACTIONS
Introduction Certaines opérations qu’un utilisateur voit comme indivisible (ex.: transfert d’argent) ne sont pas indivisibles, dans les faits (réalisées par une ou plusieurs requêtes). De plus, une requête SQL (insert, delete, select ..) est souvent réalisée par plusieurs opérations sur une BD. Pour préserver la cohérence d’une BD, il peut être important de contrôler les accès concurrents aux données et de gérer les pannes. Exemple: si de nombreuses lectures et écritures en parallèle.
Exemple A (600$) B (200$) Deux clients d’une banque: A et B. La BD indique un montant d’argent dans le compte de banque de chaque client. La banque veut faire des transferts d’argent d’un client à l’autre à partir de n’importe quelle succursale. A (600$) B (200$)
Voici le programme de transfert d’argent: Transfert(A, B, montant){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } Est-ce que ce programme est correct? A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; // 100 write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; // 100 write(A); read(B); B := B + montant; write(B); } A (100$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); B := B + montant; write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; // 100 write(A); read(B); B := B + montant; write(B); } A (550$) B (200$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); // 200 B := B + montant; // 250 write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; // 100 write(A); read(B); B := B + montant; write(B); } A (550$) B (250$)
Exemple 1 – problème d’accès concurrents Transfert(A, B, 50){ read(A); // 600 A := A – montant; // A = 550 write(A); read(B); // 200 B := B + montant; // 250 write(B); } Transfert(A, B, 500){ read(A); // 600 A := A – montant; // 100 write(A); read(B); // 250 B := B + montant; // 750 write(B); } // 750 Au début, on avait 800 $ ! Maintenant: 1300 $! (état incohérent) A (550$) B (750$)
Exemple 2 – problème causé par une panne Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } A (600$) B (200$)
Exemple 2 – problème causé par une panne Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } A (100$) B (200$)
Exemple 2 – problème causé par une panne Transfert(A, B, 500){ read(A); A := A – montant; write(A); read(B); B := B + montant; write(B); } Une panne survient… Le transfert n’est pas complété. L’argent est perdu! (état incohérent) A (100$) B (200$)
Comment gérer cela? Transaction: une série d’opérations traitées comme un tout par le SGBD (lectures/écritures). Elle s’exécute complètement ou échoue complètement. Utiliser des transactions - Peut réduire la performance, + Contribue à préserver la cohérence de la BD.
Causes d’échecs de transactions Plusieurs causes: Panne réseau, Panne du système d’exploitation, Bris matériel de l’ordinateur, Erreur logicielle, Erreur humaine, La transaction provoque une erreur (ex.: division par zéro, erreur de sécurité/privilèges…) …
Utilisation des transactions Une transaction est généralement initiée par un programme effectuant des accès à une BD (ex.: en C++ par le protocole ODBC). Au début de la transaction: un énoncé ou une méthode « start transaction » est utilisé. À la fin: « end transaction » (parfois appelé: commit()) . Une transaction peut contenir plusieurs opérations. Ex.: plusieurs requêtes SQL.
Propriétés désirables d’une transaction (ACID) Atomicité: toutes les opérations sont effectuées sur la BD ou bien aucune. Ceci est pour éviter que la BD tombe dans un état incohérent. Exemple: aucun argent n’est « perdu » si une panne survient pendant un transfert de fond. Comment s’en assurer? Le SGBD créé un historique (log) sur le disque avec les anciennes valeurs avant une écriture. Si une transaction n’est pas complétée, le SGBD restore les anciennes valeurs.
Propriétés désirables d’une transaction (ACID) Cohérence: l’exécution d’une transaction de façon isolée préserve la cohérence de la BD, si elle était cohérente avant la transaction. Exemple: aucun argent n’est « créé » ou « disparaît » comme suite à un transfert de fond, retrait d’argent ou autres opérations. La responsabilité du programmeur qui a conçu la transaction (absence de bogue…) Pourrait être facilité par tests automatiques…
Propriétés désirables d’une transaction (ACID) Isolation: les transactions en cours d’exécution ne doivent pas interférer les unes avec les autres. Exemple: un retrait d’argent et un transfert exécutés simultanément. Une solution: exécuter les transactions en série. Il est préférable d’exécuter de façon concurrente pour de meilleure performance. L’isolation est gérée par le système de contrôle des accès concurrents de la BD.
Propriétés désirables d’une transaction (ACID) Durabilité: si le système tombe en panne après l’exécution d’une transaction, son résultat ne doit pas être perdu. Ex.: si une panne survient après un retrait d’argent d’un guichet automatique, le bon solde doit être retrouvé.
Pour gérer la durabilité Si une transaction est complétée, elle ne doit pas être annulée par une panne. Comment? Le résultat d’une transaction est stocké sur un support de stockage fiable avant que la transaction ne soit complétée. Le système de recouvrement de la BD est responsable d’assurer la durabilité.
Stockage fiable Plusieurs formes: système de protections contre les pannes de courant pour éviter de perdre le contenu de la RAM, redondances aux niveaux des disques durs (ex.: RAID), différents niveaux de fiabilité peuvent être obtenus.
Un modèle simple de transaction Considérons un modèle simple: Des éléments de données A,B, C… contenant chacun une valeur. Lecture d’une valeur, écriture d’une valeur et opérations arithmétiques. Exemple: Ti: read(A); read(B); B := B + A; write(B).
États d’une transaction partiellement accomplie accomplie active échouée abandonnée active: l’état initial partiellement accomplie: quand la dernière opération a été exécutée, mais le résultat est toujours en mémoire volatile. échouée: après la découverte que la transaction ne pourra pas être terminée. Les opérations doivent être annulée… abandonnée: lorsque l’état précédant l’exécution de la transaction a été restauré. accomplie: un succès complet.
États d’une transaction (suite) Chaque opération est tout d’abord écrite dans l’historique stocké sur disque avant d’être effectuée sur la BD pour permettre de refaire ou annuler l’opération. Une transaction est dans l’état « partiellement accomplie » si toutes les opérations ont été effectuées, mais le résultat est toujours en mémoire volatile. Après l’abandon d’une transaction, l’application peut décider de l’exécuter à nouveau ou de laisser tomber (ceci dépend de l’application).
États d’une transaction (suite) Une fois qu’une transaction est accomplie (commited), elle ne peut pas être annulée. Toutefois, dans certains cas, on pourrait exécuter une transaction « inverse » pour retourner aux valeurs initiales Ex.: addition 50 $ pour annuler un retrait de 50 $.
Isolation Deux raisons d’exécuter des transactions de façon concurrente: Meilleure utilisation des ressources processeur et disque peuvent fonctionner en parallèle, (proc. multicoeurs, plusieurs ordinateurs, parallélisation des requêtes …), Donc plus de requêtes peuvent être traitées en moins de temps, Délai d’attente réduit les transactions courtes n’ont pas besoin d’attendre la fin de l’exécution de transactions plus longues).
Isolation (suite) Le système de contrôle des accès concurrents doit s’assurer que l’exécution des transactions ne provoque pas d’états incohérents. Exemple: 2 transactions: Si ces transactions sont exécutées de façon concurrente, alors, plusieurs exécutions sont possibles
Isolation (suite) Plusieurs exécutions sont possibles. Ex.: Une exécution séquentielle Une exécution concurrente Est-ce que ces exécutions génèrent le même résultat? Oui
Isolation (suite) Défis des accès concurrents: très grand nombre d’exécutions possibles pour les mêmes transactions, il est impossible de prévoir laquelle sera exécutée certaines exécutions résulteront en des états incohérents. Il faut donc idéalement un mécanisme pour s’assurer que seule les exécutions ayant le même résultat qu’une exécution séquentielle soient exécutées (exécutions sérialisables).
Exemple Ces deux exécutions résultent en un état cohérent?
Comment détecter les conflits potentiels? Considérons les opérations de lecture et d’écriture seulement. De façon générale, pour une entrée Q, si : Ta Tb read(Q) est suivi de read (Q) l’ordre n’importe pas. Dans les cas suivants, l’ordre importe: Ta Tb read(Q) suivi de write(Q) write(Q) suivi de read(Q) write(Q) suivi de write(Q) Exemple
Graphe de précédence Pour analyser les conflits, une méthode consiste à utiliser un graphe de précédence. Un graphe orienté G(V,E) V = nœuds (les transactions) E = arrêtes: read(Q) write(Q) write(Q) read(Q) write(Q) write(Q)
Exemple 1 Arrêtes: read(Q) write(Q) write(Q) read(Q) write(Q) write(Q) T1 T2 Si le graphe ne contient pas de cycle, alors l’exécution est sérialisable (donne le même résultat qu’une exécution sérielle!)
Exemple 2 Arrêtes: read(Q) write(Q) write(Q) read(Q) write(Q) write(Q) T1 T2 Si le graphe ne contient pas de cycle, alors l’exécution est sérialisable (donne le même résultat qu’une exécution sérielle!)
Graphe de précédences (suite) Si le graphe ne contient pas de cycle, alors l’exécution est sérialisable (donne le même résultat qu’une exécution sérielle) Sinon, elle peut ne pas donner le même résultat ou bien donner le même résultat. Exemple
Exemple 3 Quel est le graphe de précédence? T1 T2 Résultat cohérent? Oui (dans ce cas, parce que l’addition et la soustraction sont des opérations commutatives). Toutefois en pratique, on ne peut pas vraiment tirer avantage de ceci, car cela est dur à vérifier pour des opérations plus complexes…
Graphe de précédence (suite) Il est possible d’automatiser la vérification de conflits en appliquant un algorithme pour construire le graphe de précédence et un algorithme de détection de cycles. Un algorithme de détection de cycles nécessite typiquement O(n2) opérations pour un graphe à n arrêtes.
Propriété des graphes de précédence Un graphe de précédence est un ordre partiel. Il peut être transformé en un ou plusieurs ordres totaux.
Exécutions non recouvrables Considérons maintenant l’impact de l’échec d’une transaction sur une exécution. Ex.:
Exécutions non recouvrables Considérons maintenant l’impact de l’échec d’une transaction sur une exécution. Ex.: panne Si T6 échoue après le « commit » de T7, alors il y a un problème car T7 a lu la valeur « A » écrite par T6 et T6 n’a pas encore fait de « commit ». Cette exécution est « non-recouvrable ». Formellement
Exécutions non recouvrables (suite) Exécution non recouvrable: il existe une paire de transactions TA et TB tel qu’une transaction TA lit un élément écrit par une transaction TB, mais le « commit » de TA apparaît avant celui de TB. Il est préférable d’éviter les exécutions non recouvrables! Comment faire? Une solution: retarder le « commit » de TB jusqu’à la fin de TA.
Exécutions en cascade Exécution en cascade: une exécution est dite en cascade si l’échec d’une transaction provoque l’annulation de plusieurs transactions. Exemple: Si T8 échoue, T9 et T10 doivent aussi être annulés, car ils sont dépendant de T8. Les exécutions en cascade sont indésirables, car elles peuvent provoquer l’annulation de beaucoup de travail déjà fait. échec
Exécutions en cascade (suite) Exécution sans cascade: une exécution telle que pour chaque paire de transactions TA et TB où TA lit une valeur écrite par TB, alors l’opération « commit » de TA apparaît avant l’opération de lecture de TB. Il peut être démontré que toutes exécutions sans cascade sont recouvrables.
Niveaux d’isolation Les stratégies précédentes permettent d’éviter au programmeur de tenir compte des accès concurrents tout en garantissant une certaine sécurité. Toutefois, les stratégies présentées peuvent être trop restrictives et ainsi nuire à la performance. Pour cette raison, des définitions plus flexibles ont été définies (appelées « niveaux d’isolation »).
Niveaux d’isolation (suite) La plupart des BD relationnelles utilisant SQL offrent les quatre niveaux suivants: « read uncommitted »: toutes les données peuvent être lues par toutes les transactions. n’assure pas que les exécutions sont sérialisables. « read committed »: Les données qui ont fait l’objet d’une écriture par une transaction doivent avoir fait l’objet d’un « commit » pour être lues par une autre transaction. pour éviter les exécutions non recouvrables.
Niveaux d’isolation (suite) « repeatable read »: Même condition que le niveau précédent. De plus, une transaction ne peut pas mettre à jour un uplet entre deux lectures de ce uplet par une autre transaction. Le but est d’éviter qu’une transaction lise deux fois une valeur différente avec la même requête. Ce niveau comme les précédents n’assure pas que les exécutions sont sérialisables.
Niveaux d’isolation (suite) « serializable »: assure que toutes les exécutions sont sérialisables hormis quelques exceptions. Par défaut, la plupart des BD utilisent « read-committed » (niveau 2) (les données écrites doivent faire l’objet d’un commit pour être lues par une autre transaction.) Il est possible de changer le niveau en utilisant: « set transaction isolation level serializable » par exemple (dépend du SGBD).
Niveaux d’isolation (suite) Le choix d’un niveau d’isolation faible peut améliorer les performances, car il y a moins de temps d’attente pour de longues transactions. Toutefois, il faut utiliser ce compromis que si cela ne créé pas d’incohérences indésirables dans la BD pour l’application désirée. Ex. de situations où un compromis est acceptable: réservation de sièges pour billets d’avion, inventaire des articles vendus dans un magasin en ligne. Attention: le niveau « sérialisable » est parfois plus faible que ce qu’il devrait être pour certains SGBD.
Implémentation des niveaux d’isolation Comment implémenter les niveaux d’isolation? Plusieurs façons d’implémenter les niveaux d’isolation. Approche 1: verrous Verrouiller les éléments utilisés par la transaction et les libérer après. verrous partagés: pour des lecture(s) seulement. verrous exclusifs: pour des écriture(s) Ceci permet d’assurer la sérialisabilité. Toutefois, cela n’est pas l’approche la plus performante.
Implémentation des niveaux d’isolation Approche 2: estampilles temporelles Une estampille est assignée à chaque transaction. Chaque uplet de la BD a une « estampille de lecture » correspondant à l’estampille de la plus récente transaction qui l’a lu. Chaque uplet a aussi une « estampille d’écriture ». Les transactions qui ne respectent pas l’ordre des estampilles sont annulées et redémarrées avec une nouvelle estampille.
Implémentation des niveaux d’isolation Approche 3: plusieurs versions maintenir plusieurs versions d’un uplet pour permettre de lire une ancienne version plutôt qu’une nouvelle qui n’a pas reçu de « commit », ou bien une version qui arrive après selon l’ordre de sérialisation des transactions. cette approche est utilisée dans plusieurs SGBD.
Implémentation des niveaux d’isolation Approche 3: plusieurs versions (suite) Une variante: « snapshot isolation ». Chaque transaction a une version des éléments qu’elle utilise. Lors d’un « commit », si une autre transaction a écrit avant, alors échec, sinon les données sont écrites. Avantages: aucune attente. De plus, seules les transactions d’écriture peuvent échouer.
Transactions en SQL Par défaut, chaque requête SQL est considérée comme une transaction. Il est possible de changer cela en désactivant le « commit » automatique. À la fin d’une transaction une des deux méthodes suivantes doivent être appelée: la méthode commit() est appelée pour sauvegarder les changements. la méthode rollback() est appelée pour abandonner les changements.
Exemple http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html
Transactions en SQL (suite) En SQL, insert, update et delete sont les principales opérations d’écriture. Au niveau de la préservation des propriétés des transactions, il y a quelques cas problématiques avec SQL que nous n’avons pas couverts jusqu’à maintenant avec le modèle simple que nous avons utilisé:
Cas 1 Le résultat de ces deux requêtes dépend de l’ordre d’exécution. Soit deux requêtes SQL: Le résultat de ces deux requêtes dépend de l’ordre d’exécution. Le problème est que seuls les uplets utilisés sont considérés dans le contrôle des accès concurrents, mais que la façon de les obtenir n’est pas considérée (le WHERE). Pour régler le problème, il faudrait un mécanisme pour verrouiller un index (peu performant). Une solution: un verrou sur un intervalle.
Cas 2 Toutefois, même avec cela, il y a des cas problématiques. Exemple: Monsieur Wu a 91 000 $ initialement Il peut y avoir conflit si pour la requête de gauche, le SGBD consulte la table « instructor » au complet ou s’il utilise un index existant pour les uplets > 90000. Ceci dépend donc de l’implémentation! Pour régler ce problème, cela prendrait un mécanisme de contrôle plus complexe, mais ce n’est pas utilisé dans la pratique pour des raisons de performance.
Exercices
Cours requêtes SQL modèles entité-relation normalisation select, insert update… modèles entité-relation normalisation applications (architecture, performance et sécurité, …) transactions ….
Exemple de combinaison d’opérations Relation « Ville » Relation « Cinéma » code_ville nom 1 Montréal 2 Moncton 3 Halifax … nom fondation code_ville CinePlus 1980 1 CinemaEtoile 1970 1960 2 … Relation « Cinema_Ville » nom_cinema nom_ville CinePlus Montréal CinemaEtoile Montreal Moncton …
Relation « employe » ID nom prenom salaire 1 Parent Jean 20000 2 Arsenault Marc 30000 3 Charest Tom 50000 4 Torvald Linus 60000 5 Sawyer 90000 …
Exercice 1 Est-ce que cette exécution est sérialisable? Quel est le graphe de précédence? Est-ce que cette exécution est recouvrable ?
T1 T2 T3 T4 T5 read(A) write(A) read(C) commit read(B) write(B) read(D)
Exercice 2 Est-ce qu’un SGBD qui ne tombe jamais en panne aurait besoin d’un système de recouvrement? Oui, pour effectuer l’annulation de transactions.
Exercice 3 D’après-vous, pourquoi les 4 propriétés des transactions (cohérence, atomicité, durabilité, isolation) sont plus importantes pour les opérations d’un SGBD que pour les opérations sur les fichiers d’un disque dur? Pour des systèmes réels (banques, réservations de billets d’avions), l’atomicité et la durabilité sont cruciales. Pour un particulier, le prix (monétaire) ou en performance n’en vaut pas nécessairement la peine.
Exercice 4 Est-ce que le graphe de précédence suivant est sérialisable? Donnez un exemple d’exécution sérialisable.
Exercice 5 Est-ce qu’il y a des situations où il serait désirables d’avoir des exécutions avec cascades plutôt que sans cascade? Oui, lorsque les performances importent
Base de données Magasins.accdb
Autres exercices d’écriture de requête Obtenir le nom de tous les produits en inventaire qui ne sont pas en commande. Obtenir la moyenne du prix de vente des produits en commande pour chaque département Obtenir le nom de tous les produits qui ont un prix de vente supérieur à la moyenne.
MODÈLE ENTITÉ-RELATION AVANCÉ
Introduction Le modèle entité-relation que nous avons vu permet de modéliser la plupart des besoins pour les BD relationnelle. Toutefois, si on introduit une notation avancée, il est possible de mieux exprimer les besoins.
Spécialisation Parfois les entités d’un ensemble d’entités ne partagent pas tous les mêmes attributs. Ex.: employé et étudiant possède les même attributs d’une personne, mais peuvent aussi avoir quelques attributs spécifiques (ex.: salaire pour employé et nb_crédits pour étudiant).
Spécialisation (suite) Spécialisation: le processus de désigner des sous-groupes parmi un ensemble d’entités. Chaque sous-groupe « hérite » des attributs du groupe principal et peut avoir des attribut(s) propre(s). Ex.: Personne matricule nom adresse Employé Étudiant salaire nb_crédits Note: Une personne peut ne pas être étudiant ni employé
Spécialisation (suite) Une spécialisation d’un ensemble d’entités X est disjointe si une entité peut appartenir à plusieurs spécialisations de X. Ex.: une personne peut être à la fois employé et étudiant Personne matricule nom adresse Employé Étudiant salaire nb_crédits
Spécialisation (suite) Une spécialisation d’un ensemble d’entités X est avec chevauchement si une entité ne peut pas appartenir à plusieurs spécialisations de X. Ex.: un employé est soit secrétaire, soit chargé de cours. Employé salaire Secrétaire Chargé_cours nb_heures rang salaire
Spécialisation (suite) Une spécialisation peut être spécialisée à son tour. Ex.: Personne matricule nom adresse Employé salaire Étudiant nb_crédits Secrétaire Chargé_cours nb_heures rang
Spécialisation (suite) Un ensemble d’entité spécialisé peut participer à des relations Personne matricule nom adresse suivre cours Employé salaire Étudiant nb_crédits Cours Secrétaire Chargé_cours enseigne Sigle Sujet … nb_heures rang
Spécialisation (suite) De façon générale, il y a deux raisons de spécialiser: Certaines entités ont des attributs qui les distinguent Certaines entités participent à des relations particulières.
Généralisation La spécialisation est une approche du « haut vers le bas » où l’on raffine un modèle en divisant en sous- groupes plus détaillé. La généralisation est une approche « bas vers le haut » où l’on généralise plusieurs ensemble d’entités par leurs attributs communs. Les deux approches peuvent être utilisée et utilise la même notation
Généralisation (suite) Exemple 1: Ces deux ensembles d’entités ont pratiquement les mêmes attributs. On peut donc généraliser. Employé matricule nom adresse salaire Étudiant matricule nom adresse nb_crédits
Généralisation (suite) Exemple 1: Ces deux ensembles d’entités ont pratiquement les mêmes attributs. On peut donc généraliser. Personne matricule nom adresse Employé salaire Étudiant nb_crédits
Généralisation (suite) Exemple 2: suivre cours Employé matricule nom adresse salaire Étudiant matricule nom adresse nb_crédits affilié à affilié à Université matricule nom adresse nb_crédits
Généralisation (suite) Exemple 2: affilié à Université nom adresse Personne matricule nom adresse suivre cours Employé salaire Étudiant nb_crédits
Héritage Si un ensemble d’entité X est une spécialisation d’un ensemble d’entité Y, alors: chaque entité de X hérite des attributs de Y chaque entité de X peut participer aux relations de Y. affilié à Université nom adresse Personne matricule nom adresse Employé salaire Étudiant nb_crédits
Contraintes de participation Une spécialisation/généralisation est partielle si chaque entité de haut niveau peut ne pas appartenir ensemble d’entité de bas niveau Notation: Employé salaire Secrétaire Chargé_cours nb_heures … rang … « Un étudiant doit être soit un étudiant de 1er cycle ou un étudiant de maîtrise »
Contraintes de participation Une spécialisation/généralisation est totale si chaque entité de haut niveau doit appartenir à au moins un ensemble d’entité de bas niveau Notation: Étudiant nb_crédits totale totale 1er cycle Maîtrise est_coop? … sujet_recherche … « Un étudiant doit être soit un étudiant de 1er cycle ou un étudiant de maîtrise »
Contraintes d’appartenance La condition d’appartenance d’une entité à une spécialisation peut être: un critère sur des attribut(s) qui peut être formalisé: ex.: un programmeur est programmeur senior si experience > 5 ans. un choix subjectif par l’utilisateur de la base de données: ex.: certains employé reçoivent des responsabilités supplémentaires, au cas par cas.
Spécialisations multiples Un ensemble d’entités peut être une spécialisation de plusieurs ensembles d’entités. Syndiqué Employé # membre syndicat cotisation_totale … salaire Secrétaire Chargé_cours nb_heures … rang … Ici, Secrétaire est une spécialisation de Employé et Syndiqué
Agrégation Une limitation du modèle entité-relation est de ne pas permettre des relations vers des relations. Dans certaines situations ce serait désirable! Exemple: chaque projet a un chargé de projet pour un projet, le chargé de projet dirige des ouvriers chaque mois, le chargé de projet rempli un rapport sur le projet. Comment modéliser ?
Agrégation (suite) Utiliser une relation à 4 ? rapport nom date Pas une bonne idée, car un projet peut exister sans avoir aucun rapport… De plus, la relation d’évaluation n’est pas la même que celle de participation à un projet.
Agrégation (suite) mieux ? rapport nom date évalue pour Il y a de la redondance… nom date
Agrégation (suite) Solution: utiliser l’agrégation: L’agrégation traite la relation ternaire de l’exemple comme un ensemble d’entités. évalue rapport nom date
Passage au modèle relationnel Personne matricule nom adresse Employé salaire Étudiant nb_crédits Personne( matricule, nom, adresse) Employé(matricule, salaire) Étudiant(matricule, nb_crédits)
Passage au modèle relationnel Étudiant matricule nb_crédits totale totale 1er cycle Maîtrise est_coop? … sujet_recherche … Etudiant_1erCycle(matricule, nb_crédits, est_coop) Étudiant_maitrise(matricule, nb_crédits, sujet_recherche) Dans le cas d’une spécialisation disjointe avec participation totale, nous ne devons pas créer une table pour l’ensembles d’entités général (ici, étudiant)
Passage au modèle relationnel projet(id, budget…) chargé_de_projet(id, nom salaire …) ouvrier(id, nom salaire) rel_projet(id_chargé, id_ouvrier, id_projet) evalue(id_chargé, id_ouvrier, nom) rapport(nom, date) évalue rapport nom date
A B C G T K B C M L E H … F G …