Transazioni in MySQL 4 • Transazioni in MySQL 4 Francesco Brancati – [email protected] Cristina Pucci – [email protected] Transazioni vs Operazioni Atomiche (1) • MySQL supporta le transazioni con i metodi di memorizzazione InnoDB e BDB (BerkleyDB) – InnoDB permette di ottenere transazioni ACID • Atomic, Consistent, Isolated, Durability • Altri metodi di MySQL (come MyISAM) seguono un’altra filosofia per l’integrità dei dati: “Atomic Operations” – In pratica le tabelle MyISAM operano in modalità autocommit=1 • Il commit viene eseguito automaticamente dopo ogni transazione Interazione tra basi di dati e web Transazioni 2 Transazioni vs Operazioni Atomiche (2) • Transazioni – Pro • Maggiori funzionalità (rollback, savepoint, etc) – Contro • Necessitano di più memoria sul disco • Comportano un maggior uso della CPU • Operazioni Atomiche – Pro • Maggiore velocità a parità di integrità di dati – Contro • Problemi più difficili da codificare Interazione tra basi di dati e web Transazioni 3 Transazioni vs Operazioni Atomiche (3) • Le transazioni assicurano che gli update non finiti o archivi corrotti non vengano scritti sul database – Il server dà l’opportunità di fare rollback automatici e di salvare il database • Le operazioni atomiche possono essere rese altrettanto sicure includendo controlli prima degli updates ed eseguendo script che controllano l’integrità del database riparandolo automaticamente o comunque avvisando in caso di inconsistenze – Si usano i log di MySQL per ripristinare correttamente le tabelle senza perdita nell’ integrità dei dati Interazione tra basi di dati e web Transazioni 4 Transazioni vs Operazioni Atomiche (4) • In genere tutti i problemi d’integrità che le transazioni risolvono, possono essere risolti anche con l’uso di LOCK TABLES ed operazioni atomiche, escludendo i crash di sistema • Non esistono DBMS in grado di garantire l’integrità di dati al 100% • In MySQL è sufficiente tenere i backup dei dati ed i log binari attivati per recuperare ogni possibile situazione che possa essere recuperata con un qualsiasi altro database transazionale Interazione tra basi di dati e web Transazioni 5 COMMIT e ROLLBACK • Di default MySQL ha la variabile AUTOCOMMIT abilitata – Appena si esegue un statement che comporta una modifica al database, MySql memorizza il risultato sul disco • Con tabelle transazionali è necessario disabilitare autocommit per sfruttare la funzionalità di rollback – Set autocommit=0; – Attenzione: quando autocommit è disabilitata è necessario fare sempre il commit per rendere permanenti i cambiamenti Interazione tra basi di dati e web Transazioni 6 START TRANSACTION • Se si vuole disabilitare temporaneamente AUTOCOMMIT per una serie di statement si usa START TRANSACTION START TRANSACTION; SELECT * FROM table1 WHERE type=1; UPDATE table2 SET summary=“A” WHERE type=1; COMMIT; – Autocommit rimane disabilitata finché non si esegue un commit o un rollback • E’posibile modificare il livello di isolamento della transazione (globalmente o per la sessione corrente) utilizzando SET TRANSACTION ISOLATION LEVEL – READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ (default), SERIALIZABLE Interazione tra basi di dati e web Transazioni 7 Statement che causano un COMMIT implicito • Ognuno dei seguenti comandi implicitamente termina una transazione, come se fosse eseguito un COMMIT prima di eseguire il comando: ALTER TABLE BEGIN CREATE INDEX DROP DATABASE DROP INDEX DROP TABLE LOAD MASTER DATA LOCK TABLES RENAME TABLE SET AUTOCOMMIT=1 START TRANSACTION TRUNCATE TABLE • Comandi che non ammettono ROLLBACK – In genere, tutti i comandi DDL (create, drop, alter, etc.) – Le transazioni non dovrebbero contenere suddetti comandi che invaliderebbero l’effetto di un rollback. Interazione tra basi di dati e web Transazioni 8 SAVEPOINT e ROLLBACK TO SAVEPOINT • Lo statement SAVEPOINT permette di salvare lo stato di una transazione. • Se la transazione corrente ha un savepoint con lo stesso nome, il vecchio savepoint viene cancellato e ne viene settato uno nuovo. – SAVEPOINT identifier • ROLLBACK TO SAVEPOINT riporta una transazione al savepoint nominato. – Le modifiche che la transazione corrente fa dopo il savepoint risultano nulle. – ROLLBACK TO SAVEPOINT identifier Interazione tra basi di dati e web Transazioni 9 LOCK TABLES ed UNLOCK TABLES (1) • Sintassi: LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...UNLOCK TABLES • LOCK TABLES blocca una o più tabelle per il processo corrente. • UNLOCK TABLES rilascia ogni lock mantenuto dal processo corrente. – Tutte le tabelle bloccate dal processo corrente sono implicitamente sbloccate quando il processo dichiara un altro LOCK TABLES o quando la connessione al server viene chiusa Interazione tra basi di dati e web Transazioni 10 LOCK TABLES ed UNLOCK TABLES (2) • Quando si usa LOCK TABLES è nesessario bloccare tutte le tabelle che si utilizzeranno nelle query. – Non è possibile accedere a nessun’altra tabella non bloccata • Non è possibile usare più volte una tabella bloccata in una singola query: si usano gli alias. – mysql> LOCK TABLES t WRITE, t mysql> INSERT INTO t SELECT * ERROR 1100: Table 't' was not mysql> INSERT INTO t SELECT * AS t1 WRITE; FROM t; locked with LOCK TABLES FROM t AS t1; • Bloccando la tabella non si bloccano anche gli alias e viceversa – mysql> LOCK TABLES t READ; mysql> SELECT * FROM t AS myalias; ERROR 1100: Table 'myalias' was not locked with LOCK TABLES Interazione tra basi di dati e web Transazioni 11 LOCK TABLES e tabelle transazionali • LOCK TABLES non è transaction-safe ed esegue un commit implicito di ogni transazione attiva prima di provare a bloccare le tabelle – • Iniziare una transazione (es. con START TRANSACTION) implicitamente causa un UNLOCK TABLES. Uso corretto di LOCK TABLES con tabelle transazionali (InnoDB): 1. 2. impostare AUTOCOMMIT = 0 non eseguire UNLOCK TABLES prima del commit esplicito della transazione. • Quando si fa un LOCK TABLES, InnoDB blocca internamente le tabelle, e MySQL fa lo stesso. InnoDB rilascia il lock al successivo commit, mentre MySQL rilascerà il proprio solo quando verrà chiamato UNLOCK TABLES. Se AUTOCOMMIT = 1 InnoDB rilascia il blocco immediatamente dopo la chiamata a LOCK TABLES e si possono facilmente verificare deadlock. – • A partire dalla versione 4.1.9 non viene acquisito il lock da InnoDB se AUTOCOMMIT=1. ROLLBACK non rilascia i lock delle tabelle Interazione tra basi di dati e web Transazioni 12 LOCK TABLES e tabelle non transazionali Tecniche per lavorare con tabelle che non supportano transazioni: Usare LOCK TABLES per bloccare le tabelle a cui si vuole accedere Testare le condizioni che devono essere vere prima di realizzare l’update Eseguire l’update solo se tutto è a posto Usare UNLOCK TABLES per rilasciare i blocchi 1. 2. 3. 4. • Solitamente questo metodo è più veloce dell’utilizzo di transazioni con possibile rollback. Problema: • – Se il processo viene terminato nel mezzo di un update, tutti i lock vengono rilasciati, e non è garantito che tutti gli update siano stati eseguiti Interazione tra basi di dati e web Transazioni 13 READ e WRITE LOCK • Se un processo ottiene un READ LOCK su una tabella, questo e tutti gli altri processi potranno solo leggere dalla tabella. • Se un processo ottiene un WRITE LOCK su una tabella, solo il processo che ha bloccato può scrivere sulla tabella. Gli altri sono bloccati in scrittura finchè il lock non viene rilasciato. • Differenza fra READ LOCAL e READ: – READ LOCAL permette l’esecuzione di istruzioni INSERT non-conflicting (concorrenti) durante il blocco della tabella. – Per InnoDB READ LOCAL non esegue il lock delle tabelle. • L’uso di READ LOCAL per tabelle InnoDB è sconsigliato, si ottiene lo stesso risultato facendo una SELECT senza dover inserire nessun blocco. Interazione tra basi di dati e web Transazioni 14 WRITE LOCK • I lock in scrittura normalmente hanno priorità maggiore dei lock in lettura, questo assicura che gli update siano processati il prima possibile. – – Se un processo ottiene un READ lock ed un altro richiede un WRITE lock, le richiese di READ lock seguenti attenderanno finquando il processo scrittore abbia ottenuto il WRITE lock e lo abbia rilasciato Si possono usare blocchi LOW_PRIORITY WRITE per permettere agli altri processi di ottenere READ lock mentre il processo attende per il WRITE lock. • Si dovrebbero usare LOW_PRIORITY WRITE locks solo se si è sicuri che ci sarà un momento in cui nessun processo chiederà un READ lock. Interazione tra basi di dati e web Transazioni 15 LOCK TABLES e DEADLOCK • Algoritmo di LOCK TABLES : 1. Ordina in un modo predefinito dal sistema tutte le tabelle che devono essere bloccate. 2. Se una tabella deve essere bloccata sia con un read che con un write lock, sposta il write lock prima del read lock. 3. Blocca una tabella per volta finché il processo non ottiene tutti i lock richiesti. • Questa politica assicura che il bloccaggio della tabella non provochi deadlock. Interazione tra basi di dati e web Transazioni 16 Esempio sull’uso di LOCK TABLES • Questo esepio richiede LOCK TABLES per un’esecuzione “safe” – mysql> LOCK TABLES fatture READ, fornitori WRITE; mysql> SELECT SUM(importo) FROM fatture WHERE fornitore_id=qualche_id; mysql> UPDATE fornitori -> SET totale=somma_precedente -> WHERE fornitore_id=qualche_id; mysql> UNLOCK TABLES; – senza LOCK TABLES è possibile che un altro processo inserisca una nuova riga nella tabella fatture tra l’esecuzione della SELECT e l’UPDATE. Interazione tra basi di dati e web Transazioni 17 Risorse • • • • • http://freephp.html.it/ http://www.risorse.net/ http://www.php.net/ http://smarty.php.net/ http://www.mysql.com/ Interazione tra basi di dati e web Risorse 18