Basi di dati II – Lezione 3 – 09/10/2008 – Caputo Domenico – Cosimo, Francesco Pichierri Transazioni - Parte 1 Le transazioni hanno a che fare con la programmabilità delle basi di dati. Prima di trattarle è necessaria una premessa sulle caratteristiche di Microsoft SQL Server. Accedendo alla sua User Interface (chiamata Management Studio), dalla colonna a sinistra si potrà accedere all’elenco dei database presenti. Per ogni database si potrà accedere alle tabelle (cioè i dati memorizzati), le view e le stored procedure. Le view sono una delle caratteristiche più importanti del DBMS.Per poterle descrivere si parte da 2 tipi di entità (ad esempio CLIENTE e PRODOTTO) e una relazione ACQUISTA che le lega): Mediante l’algoritmo di mapping si passa alla realizzazione delle tabelle. Poi è possibile,a partire dall’EER, definire delle direzioni a cui si assegna una interpretazione su come vanno lette i tipi di entità e la relazione. In figura sono mostrate tre direzioni che hanno il seguente significato: A) Dato un cliente, voglio sapere quali prodotti ha acquistato B) Dato un prodotto voglio sapere da quanti e quali clienti è stato acquistato C) Dato un prodotto voglio sapere da quale cliente è stato acquistato e quali altri prodotti ha acquistato Queste direzioni rappresentano proprio le view. Il passo successivo è passare alla User Interface a partire dalla base di dati. Le interfacce vanno realizzate immaginando tutti gli utenti coinvolti: questo porta come primo passo alla individuazione degli User Types del database. Poi si passa alla individuazione dei goal (obiettivi) per ognuno in modo da arrivare ai requisiti. Si mostra un esempio per un’attività di commercio elettronico: Il passo successivo è disegnare una user interface per ogni tipo di utente. Per far ciò mi devo chiedere: “l’utente vede tutto o parte del DB?”. Questa domanda porta alla realizzazione del visibility design (cioè cosa l’utente vede del DB). Ad esempio,sempre considerando il commercio elettronico, l’utente non vedrà i prodotti che non sono più in commercio, mentre il magazziniere e il cassiere avranno sempre una visione completa. Oppure il cliente non vedrà gli altri clienti mentre il venditore avrà questa possibilità. Nel database devo individuare due tipologie di oggetti: singoli e insiemi. Da un oggetto singolo potrò avere solo una vista di dettaglio. Nel caso dell’esempio del commercio elettronico ci sarà un solo cliente che vede un insieme di oggetti (l’elenco dei prodotti). Ora ci sono gli elementi per la realizzazione della user interface. Mettendoci nel ruolo del tipo di entità devo riuscire a vedere: - Tutti i dati di dettaglio - Tutte le relazioni A questo proposito abbiamo le seguenti interpretazioni: - il cliente vede solo sé stesso il cliente vede i propri dati personali - il cliente vede gli acquisti si ha l’oggetto acquisti -il cliente vede i prodotti si ha l’oggetto catalogo Si ha questa rappresentazione: La pagina “Dati Personali” deve portare ad una vista di dettaglio sui dati del cliente, quindi si passerà ad un’altra pagina. La pagina “Acquista” deve portare a un insieme di oggetti. La pagina “Catalogo” porterà alla pagina “Insieme prodotto”, che rappresenta l’insieme degli oggetti di tipo prodotto. A sua volta la pagina “Insieme prodotto” porterà alla vista di dettaglio del prodotto. Il discorso è analogo per gli acquisti. Questo discorso porta a due tipologie di viste: - Vista di insieme: ad esempio l’elenco di tutti i prodotti - Vista di dettaglio: ad esempio tutti i tipi di attributi dell’oggetto PRODOTTO e gli attributi calcolati, cioè i nomi dei clienti che comprano il prodotto e, da questi , gli altri prodotti che sono stati comprati dai clienti. La regola che bisogna seguire è quindi la seguente: “ci si posiziona su ogni tipo di entità e si visualizzano tutti i dati memorizzati e tutti i dati calcolati che si possono ottenere dalle relazioni” Riassumendo quanto detto finora, si sono individuati tre passi: 1- Goal e casi d’uso 2- Visibility Design 3- Interfacce (viste di insieme e di dettaglio) Le view introdotte all’inizio della lezione permettono di costruire le interfacce. Va osservato che anche sul database più semplice posso avere infinite viste. Come esempio si prenda il tipo di entità PERSONA e la relazione FIGLIO_DI: È_figlio _di PERSONA Se si considera la relazione di parentela posso avere quindi infinite direzioni. Stored Procedures La programmazione può essere classificata in tre categorie: 1- IMPERATIVA 2- DICHIARATIVA 3- FUNZIONALE Quella di interesse è la programmazione dichiarativa. In questa categoria ci si chiede cosa si vuole: la risposta la fornisce direttamente il PC poiché gli algoritmi sono stati già implementati. NOTA: secondo la teoria relazionale, qualunque informazione serva estrarre da un database, posso ottenerla con un solo comando. Le stored procedure sono essenzialmente delle transazioni. Va ricordato che c’è una differenza tra una transazione e un programma: le transazioni non sono programmi! Esse derivano dal problema della concorrenza in un database (la concorrenza nasce da un problema di competizione). Le transazioni devono soddisfare quattro requisiti (devono essere ACID): -Atomiche: per il PC esse devono essere eseguite in un’unica operazione -Consistenti -Isolate: cioè si deve dare l’impressione che in un qualunque momento il database venga usato da una sola persona(dalla persona che stà richiedendo la transazione) -Durevoli: l’effetto di una transazione può essere annullato solo da un’altra transazione Le stored procedures nascono quindi dal fatto che ci sono operazioni complesse (cioè le transazioni) che devono soddisfare le quattro proprietà descritte. Per effettuare una transazione è necessario effettuare sei operazioni: 1) Read(X) 2) Write (X) 3) BEGIN TRANSACTION 4) COMMIT 5) ROLL BACK 6) END TRANSACTION Si descrive ora il processo di lettura e scrittura su un disco: il processo di lettura è composto da 3 passi: 1) Ricerca indirizzo del blocco 2) Copia del blocco dal disco alla memoria 3) Copia il dato X dal blocco alla variabile di programma che lo contiene Invece il processo di scrittura è composto da quattro passi: 1) Indirizzo del blocco in cui mettere il dato 2) Caricamento del blocco nel buffer 3) Copia del dato X nel blocco 4) Scrittura del blocco sul disco Va osservato che né la lettura né la scrittura sono operazioni atomiche. Si possono verificare degli errori tra un passo e l’altro. In dettaglio ci sono quattro tipi di errori: 1) LOST UPDATE 2) TEMPORARY UPDATE 3) INCORRECT SUMMARY 4) UNREPEATABLE READ: cioè leggendo la stessa variabile due volte a distanza di tempo, il suo valore cambia e non possiamo sapere se è dovuto ad un errore o un cambiamento previsto. E’ possibile effettuare la serializzazione totale delle transazioni, ma sono richiesti dei calcoli eccessivi per il PC, quindi ci si accontenta di conteggi approssimativi (che non significa dati approssimati!). Si mostrano ora i primi 3 errori mediante questa sequenza di istruzioni: Nel problema #2 sembra che non ci siano problemi: in realtà se la transazione A non va a buon fine allora bisogna effettuare il roll-back della transazione di A e quindi il valore di X di A dovrebbe anche essere ripristinato, ma B ha già letto il valore di X della transazione parziale. La transazione può essere bloccata per tre motivi: 1) COMPUTER FAILURE: si rimediare adottando i bit di ridondanza per la correzione degli errori (ECC) 2) TRANSACTION ERROR: è il caso visto, in cui si ritorna indietro 3) DISK FAILURE: si può rimediare mediante sistemi RAID. Prima di scrivere una transazione, si mostra il diagramma degli stati di una transazione. In questo diagramma si fa uso delle sei istruzioni già elencate: Ora si può scrivere la prima transazione: EXEC SQL WHENEVER SQLERROR GO TO UNO; EXEC SQL SET TRANSACTION READ WRITE DIAGNOSTIC SIZE 5 ISOLATION LEVEL SERIALIZABLE; EXEC SQL INSERT INTO EMPLOYEE(Fname, Lname) VALUES (‘Mario’,’Rossi’); EXEC SQL UPDATE EMPLOYEE SET SALARY = SALARY * 1.1 WHERE DNO = 2; EXEC SQL COMMIT; GO THE_END; UNDO: EXEC SQL ROLLBACK; THE_END: EXIT 0; La riga con DIAGNOSTIC SIZE serve per ricordare comandi precedenti. E’ utile solo nel debug. La stringa SERIALIZABLE indica che non sono permessi errori di lettura e/o scrittura di nessun genere. Solo nel momento in cui si arriva all’istruzione EXEC SQL COMMIT i dati precedenti vengono scritti effettivamente: vi sono infatti delle tecniche che scrivono in un colpo solo i dati nel database. Quindi finchè la transazione non è finita, non scrivo nulla nel disco e nel caso di errore annullo tutte le operazioni effettuate fino a quel momento.