MySQL 4 Oracle DBAs

MySQL e' il piu' diffuso tra i DBMS relazionali Open Source, Oracle e' invece il piu' diffuso tra gli RDBMS commerciali. Non e' cosi' improbabile quindi che capiti di passare dall'uno all'altro...
Questo documento cerca di presentare le principali differenze tra i due RDBMS permettendo cosi' ad un DBA Oracle di lavorare in breve tempo ed efficacemente con MySQL.

Il documento e' organizzato in brevi capitoli: Ho fretta!, Elementi comuni, Data Types, Transazioni, Funzioni ed operatori, Performance ed Ottimizzatore, Repliche, Varie ed eventuali, Stored Procedures, Strumenti, Installazione ed amministrazione, Configurazione, Security, Architettura ( Clustering, Replication ), Programmazione, Compatibilita' Oracle 100%, Gateway, Futuro, ...

Per una descrizione generale su MySQL conviene leggere Introduzione a MySQL, Qualcosa in piu' su MySQL, MySQL 5.0: le novita', MySQL 5.1: le novita', ...
Naturalmente la migliore e piu' completa sorgente di informazioni e' il sito ufficiale MySQL ed in particolare i manuali on-line.

Su Oracle la documentazione e' sterminata... C'era una volta Oracle, Introduzione ai database relazionali ed ad Oracle, I piu' comuni errori su Oracle, Novita' presenti in Oracle 10g (R2 review), Corso: Linguaggio SQL su Oracle, Corso: Amministrazione Oracle, Corso: PL-SQL, ... ed altri centinaia di ottimi documenti e siti web (ottimi anche perche' non scritti da me!).
Le migliori e piu' aggiornate sorgenti di informazione sono il sito ufficiale Oracle ed il sito di supporto Metalink (con accesso riservato).

Questo documento e' stato preparato con la versione 5.0 di MySQL (5.0.24) e la versione 10g R2 (10.2.1.0) di Oracle su un Linux ma e', mutatis mutandis, valido anche per altre versioni.

Ho fretta!

Ho fretta e voglio lavorare subito con MySQL!
In questo capitolo vengono riportati gli elementi per lavorare immediatamente. Ovviamente gli stessi elementi verranno ripresi nel seguito in modo piu' completo ed organizzato...
Insomma, supponiamo di avere un MySQL installato e funzionante su un bel sistema Linux. Come facciamo a farci un giro?

Al posto dell'sqlplus come interfaccia da linea di comando usiamo mysql. In un'installazione di default non c'e' bisogno di specificare username e password: e' supportato l'utente Anonymous nelle connessioni da localhost. Volendo accedere ad un differente sistema, con utenza e password il comando e': mysql -h hostname -u username -p.
mysql funziona come l'sqlplus, ha meno comandi di formattazione ma e' piu' "moderno" (ad esempio si possono utilizzare le frecce per scorrere tra i comandi). Con help otteniamo la lista dei comandi MySQL e con help select otteniamo l'help sulla clausola di select. Con show XX si ottengono informazioni sullo stato di XX, dove XX puo' essere un fracco di cose!
Con show databases; si ottiene l'elenco dei database (in terminologia MySQL, per Oracle sarebbero gli schema). Con il comando SQL use mysql indichiamo che vogliamo utilizzare il database mysql (che e' sempre presente). Da ora in poi tutti i comandi SQL (eg. select * from user) cercheranno le tabelle nel DB corrente. Naturalmente e' possibile richiedere tabelle da database differenti con la sintassi select * from mysql.user. Il data dictionary e' contenuto nel database information_schema.

Utilizzare in Client/Server mysql e' molto semplice. Disponendo di un'unica installazione e di un unico servizio (che risponde alla porta 3306) e' sufficiente il nome dell'host per accedere ai dati. Non e' quindi necessario configurare un tnanames.ora o utilizzare complesse stringhe di connessione. Tipicamente ogni applicazione utilizza un database differente quindi la configurazione "applicativa" tipica richiede: host, user, password e database.

Dopo l'installazione viene generato un utente root con accesso da localhost con tutti i diritti ed un utente anonimo da localhost con diritti di selezione. E' poi possibile modificare tali accessi con i normali comandi di GRANT oppure agendo direttamente sulle tabelle di autorizzazione con l'SQL e quindi sincronizzando il server con FLUSH PRIVILEGES.

In MySQL vi sono differenti modalita' di accesso ai dati chiamati Engine. L'Engine di default e' MyISAM che e' molto veloce in query e richiede poca memoria. L'Engine InnoDB invece supporta in modo completo le transazioni ed e' adatto ad ambienti piu' complessi. Ve ne sono diversi altri (Memory, Archive, ...) adatti a scopi specifici. E' possibile scegliere l'Engine piu' adatto su ogni singola tabella.

In generale, con le opzioni di default, l'SQL di MySQL e' molto piu' permissivo. Se in un comando vi sono errori, mancano valori di default, sono necessarie conversioni... l'interprete MySQL ci mette una pezza: eseguendo comunque lo statement e segnalando un warning. Prooova!

Elementi comuni

Oracle e MySQL sono due ottimi database relazionali basati sull'SQL. In realta' gli elementi comuni sono piu' delle differenze. L'SQL e' al 95% identico: ANSI standard SQL:2003 anche se entrambe i DBMS hanno estensioni e personalizzazioni. I tipi di applicazioni supportate e supportabili, le piattaforme su cui sono disponibili, il linguaggio (ovviamente il C) con cui sono stati scritti... sono gli stessi!
Quindi il primo tentativo quando non si sa se e' supportata una funzionalita', se una clausola e' presente... e' quella di provare con la stessa sintassi!

Una volta era importante il confronto sui limiti che avevano i DB... con le attuali versioni, a meno di requisiti particolari, i limiti di MySQL e di Oracle sono talmente ampi che non ha senso confrontarli. Quindi la dimensione massima del DB, la dimensione massima di un BLOB, il numero massimo di colonne per tabella, di colonne in un indice, il massimo ed il minimo numero rappresentabili, il numero di cifre significative di un numero, ... oramai sono limiti talmente ampi su entrambe gli RDBMS che non hanno importanza per la maggioranza delle configurazioni.
Anche l'assenza del supporto delle transazioni, la gestione delle subquery, la mancanza delle viste, l'assenza di stored procedures, ... spesso riportati come difetti di MySQL, sono relativi a versioni molto vecchie del prodotto. Le versioni piu' recenti supportano perfettamente, anche se a volte in modo diverso da Oracle, tali funzionalita'.

Riassumendo: le parti comuni sono molte!
Nel seguito riporteremo le principali differenze organizzate (o disorganizzate) come segue: Ho fretta!, Data Types, Transazioni, Funzioni ed operatori, Performance ed Ottimizzatore, Replication, Varie ed eventuali, Stored Procedures, Strumenti, Installazione ed amministrazione, Configurazione, Security, Architettura, Programmazione, Gateway, Compatibilita' Oracle 100%, Futuro, ...

Data Types

I Data Type supportati da entrambe i DB sono molteplici e vi sono parecchie differenze, anche per la presenza in MySQL di Engine con funzionalita' specifiche.

I principali Datatype numerici MySQL sono: TINYINT SMALLINT MEDIUMINT INT BIGINT FLOAT DOUBLE DECIMAL
Per i datatype numerici le differenze principali con Oracle sono sulla scala e la precisione. MySQL e' piu' selettivo e consente di scegliere un datatype che richiede meno spazio...
In MySQL non vi sono SEQUENCE. In effetti non servono: basta definire una colonna come SERIAL che corrisponde a BIGINT UNSIGNED NOT NULL AUTO_INCREMENT.

I principali Datatype per stringhe MySQL sono: CHAR(M) VARCHAR(M) BINARY(M) VARBINARY(M) TINYBLOB TINYTEXT BLOB TEXT MEDIUMBLOB MEDIUMTEXT LONGBLOB LONGTEXT
Per i datatype stringa una importante differenza e' che MySQL consente di specificare, colonna per colonna, il character set e la collation.
Con i campi CHAR, VARCHAR e TEXT su Engine MyISAM e' possibile definire indici FULLTEXT (ovvero che consentono la ricerca all'interno dell'intero testo con la clausola MATCH).

I principali Datatype sulle date MySQL sono: DATE DATETIME TIMESTAMP TIME YEAR
Con il datatype TIMESTAMP MySQL si evita una selezione sulla pseudo colonna SYSDATE come avviene Oracle. L'assegnazione del valore e' piu' efficiente e non richede una SELECT.

Vi sono anche altri datatype meno usati (BIT, BOOL, ENUM, SET, ...). Non tutti i datatype MySQL sono utilizzabili con tutti gli Engine di MySQL oppure possono avere funzionalita' limitate. Con MySQL, come con Oracle, vi sono sinonimi ed abbreviazioni... quindi vengono accettati anche altri nomi per i datatype (eg. INTEGER).

Naturalmente e' possibile indicare attributi sulle colonne (eg. NOT NULL) con tante piccole differenze tra i due RDBMS ma non cosi' significative da riportarle tutte.
MySQL non dispone di molti dei CONSTRAINT di Oracle. E' possibile dichiarare le foreign key ma solo l'Engine InnoDB le supporta in modo completo (e comunque in modo differente da Oracle).

Riassumendo, oltre alle SEQUENCE che in MySQL non esistono, le strutture Oracle che non hanno un equivalente in MySQL sono: TYPE, materialized view, dimension, bitmap index, global partitioned index.
Mentre riassumere le differenze... e' impossibile! In ogni caso per avere un comportamente simile ad Oracle l'unica possibilita' e' quella di utilizzare l'Engine InnoDB (almeno per ora).

Transazioni

Per disporre di un supporto completo delle transazioni in MySQL e' necessario utilizzare l'Engine InnoDB. Quindi in questa sezione consideriamo siano utilizzate tabelle definite su tale Engine. La sintassi da utilizzare e'

CREATE TABLE ...
 ENGINE=INNODB;

Con InnoDB vi e' il supporto completo delle transazioni (ACID), i lock sono mantenuti a livello di riga e vi e' una gestione completa della deadlock detection. L'unica avvertenza e' quella di impostare la variabile AUTOCOMMIT a 0 (con SET AUTOCOMMIT=0;) poiche' in MySQL e' abilitato di default.

InnoDB implementa tutti gli isolation level previsti dallo standard ANSI: read uncommitted, read committed, repeatable read, serializable. Il default di MySQL e' repeatable read che rende tutte le selezioni di dati consistenti all'interno di una transazione. Il default di Oracle e' il meno stringente read committed.
L'isolation level di MySQL puo' essere variato impostando il file di configurazione oppure interattivamente con il comando:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
InnoDB gestisce anche le foreign key.

Con tali settaggi il comportamento di MySQL e' simile a quello di Oracle.
Utilizzando InnoDB si hanno anche le funzionalita' di backup on-line, recovery Point in time, ... e naturalmente il maggior onere di gestione per ripulire i log!

Funzioni ed operatori

L'insieme delle funzioni e gli operatori che Oracle fornisce a corredo del proprio SQL e' molto ampio. Anche MySQL ha un ampio numero di funzioni ed operatori. Trattandosi di estensioni dell'SQL le differenze presenti sono notevoli. Vediamo nel seguito solo alcuni esempi:

MySQL ha un insieme completo di funzioni logiche: CASE, IF(), IFNULL(), NULLIF() che sostituiscono egregiamente DECODE(), NVL(), ... di Oracle.
Il numero di funzioni matematiche e numeriche fornito da MySQL e' molto completo e comprende anche funzioni statistiche e random.
L'operatore || in MySQL e' un OR logico e non la concatenzione di stringhe! CONCAT() e' la funzione per la concatenazione di stringhe. Sono fornite diverse funzioni per il confronto di stringhe compresa la gestione delle espressioni regolari e le ricerche Full-Text.
Le funzioni di gestione delle date e le conversioni di formato sono completamente differenti da quelle Oracle! Le date vengono convertite in stringhe o in numero in modo automatico ed intuitivo. Ad esempio:

SELECT ename FROM emp
WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= hiredate;
        -> SCOTT

mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215

mysql> SELECT CURTIME();
        -> '23:50:26'

mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
        -> 'Saturday October 1997'
C'e' anche SYSDATE()... ma e' meglio utilizzare NOW().
Vi e' un repertorio completo di funzioni di compressione e crittografia (eg. COMPRESS(), MD5(), SHA(), AES_ENCRYPT(), DES_ENCRYPT(), DECODE(), ...).
Qualche funzione informativa: DATABASE() o SCHEMA() restituiscono il database corrente. VERSION() riporta la versione di MySQL. CURRENT_USER() riporta l'utente corrente cosi' come e' stato autenticato da MySQL. USER() riporta l'utente corrente cosi' come l'utente si e' connesso. CONNECTION_ID() riporta l'identificativo della connessione (simile al SID in Oracle).
ROW_COUNT() riporta il numero di righe modificate dallo statement di DML precedente. FOUND_ROWS() riporta il numero di righe trovate dalla selezione precedente. In MySQL non si utilizza il ROWNUM per limitare il numero di righe ma bensi la clausola LIMIT, con FOUND_ROWS() si puo' conoscere il numero totale di righe senza eseguire nuovamente la query.
Sono utili alcune funzioni e clausole di gruppo specifiche di MySQL. Con GROUP_CONCAT() vengono riportati in modo concatenato i valori di una colonna non raggruppata. Indicando GROUP BY ... WITH ROLLUP vengono inserite righe aggiuntive con la somma dei valori per gruppi.

Prestazioni ed ottimizzatore

Il discorso sulle prestazioni dei due RDBMS e' molto ampio e controverso. MySQL e' molto piu' leggero nelle connessioni e sui semplici accessi ai dati. Questo lo rende piu' efficiente di Oracle in molti scenari applicativi (eg. applicazioni web a 3 livelli). Di converso la gestione delle transazioni, con un numero elevato di utenti e di accessi concorrenti, viene tipicamente meglio supportata da Oracle.
Insomma entrambe possono sostenere di essere i migliori!

Le differenze sull'ottimizzatore sono parecchie. MySQL non ha tutte le strutture dati che Oracle supporta (eg. bitmapped indexes) e Oracle non ha un equivalente degli Storage Engine... L'analyze statistica sulle tabelle/colonne in MySQL e' molto meno dettagliata [NdA solo dalla versione MySQL 8.0 vengono raccolti gli istogrammi]. Il partitioning e' supportato in MySQL dalla 5.1... Quindi un confronto diretto non e' possibile. L'architettura degli Engine di MySQL offre in ogni caso molta flessibilita' e permette di scegliere la struttura ottimale per ogni oggetto.
MySQL non ha una LIBRARY CACHE in senso stretto ma dispone di diversi parametri specifici (molti dei quali relativi agli Engine) come avveniva in Oracle 6 (ricordate?). MySQL non precompila il codice SQL ma lo esegue direttamente. MySQL possiede una QUERY CACHE molto efficace: nel caso in cui la stessa query venga ripetuta questa non viene piu' eseguita ma viene restituito il result set mantenuto in cache. Magico! E' una tecnica che ho visto implementata in molti DSS ma che Oracle non ha!
Entrambe i DB hanno funzionalita' molto sofisticate (eg. query result cache in MySQL, library cache in Oracle) che li rendono particolarmente efficienti. La configurazione di MySQL e' piu' semplice di quella Oracle ma, se si sfruttano in modo pesante le possibilita' dell'Engine InnoDB, anche il tuning di MySQL richiede attenzione ed esperienza.

Ottenere l'EXPLAIN PLAN con MySQL e' molto semplice:

EXPLAIN [EXTENDED] Select statement
Anche la sintassi per fornire gli hint all'ottimizzatore e' semplice ed utilizza le clausole [ USE | FORCE | IGNORE ] INDEX.
L'ottimizzatore di Oracle e' molto piu' completo e complesso. Tuttavia nel tempo anche quello MySQL si e' arricchito. Nelle versioni piu' recenti e' possibile agire con switch specifici:
SET optimizer_switch='index_merge_union=off,index_merge_sort_union=off';
Gli switch disponibili sono:

Con la 5.7 cambia tutto perche'... sono disponibili gli HINT anche sugli statement SQL con la sintassi /*+ */ insomma come in Oracle!
Sono inoltre disponibili gli Index Hints che sono sintatticamente differenti perche' dichiarati nella clausola FROM.
La versione 8.0 fornisce ulteriori HINT, gli indici invisibili, gli indici DESC, gli indici funzionali, la gestione degli istogrammi nell'ANALYZE, il CTE, le window function, ...

In MySQL esiste anche un analogo del tkprof, si tratta del comando mysql_explain_log che analizza il general query log producendo un risultato di semplice interpretazione.

Repliche

MySQL offre una completa gestione delle repliche basata sull'applicazione dei log logici. Alcune funzionalita' sono simili a quelle degli snapshot, delle istanze in Standby o dell'Advanced Replication di Oracle ma la gestione e' molto piu' semplice.

In pratica viene definito un database master su cui vengono raccolti i log delle transazioni ed uno o piu' server slave su cui vengono ribaltate le modifiche contenute nel binary log. Gli slave sono tipicamente database in sola lettura ma non hanno particolari limitazioni d'utilizzo. A tutti gli effetti quello che avviene e' che vengono applicate tutte le modifiche SQL occorse sul master e registrate sul binary log.
Mediante opzioni e' possibile indicare sul master quali database vengono registrati (opzioni --binlog-do-db --binlog-ignore-db). Analogamente sugli slave e' possibile indicare a livello di database e di tabella quali oggetti debbano essere replicati (opzioni --replicate-*). Nel caso piu' semplice si ha una configurazione Master/Slave, in quelli piu' complessi si possono avere configurazioni multi Master con filtri personalizzati.
La replicazione di MySQL non gestisce il two phase commit: e', come in effetti dice il nome, una replicazione e non un DB distribuito.

Un discorso completamente differente vale invece per l'Engine NDB che realizza una configurazione in cluster Active-Active di MySQL. Con tale Engine si ha realmente un DB distribuito. L'analogo per Oracle e' la configurazione in RAC. Maggiori informazioni si trovano in questo documento. La soluzione MySQL ha forse piu' limiti ma e' piu' semplice da configurare e da gestire.

Simile ai database link di Oracle e' invece il Federated Engine di MySQL descritto piu' avanti nell'architettura. In ogni caso l'engine Federated e' notevolmente inferiore come funzionalita' e robustezza rispetto ai DB link e, nelle ultime versioni, e' disabilitato.

Varie ed eventuali

In MySQL non c'e' la famosa tabella DUAL ma non c'e' bisogno: e' possibile utilizzare una SELECT senza la clausola FROM. Anzi, per essere precisi, la tabella c'e' per compatibilita', ma non serve a nulla!

Il Data Dictionary e le varie viste prestazionali fornite da Oracle sono molto piu' completi di quanto fornito da MySQL. Molte informazioni sullo stato del DB in MySQL possono comunque essere ottenute con il comando SHOW.

La versione 5.0 di MySQL ha introdotto una serie molto ampia di funzionalita' coprendo cosi' gran parte delle mancanze rispetto ad Oracle. Ma e' anche vero il viceversa! Alcune delle funzionalita' introdotte di recente in Oracle erano gia' presenti in MySQL... La gestione delle regular expression (disponibile con Oracle 10g) e' presente da tempo in modo completo in MySQL.

Per migliorare la portabilita' dell'SQL e' possibile indicare il codice specifico MySQL con /*! MySQL-specific code */. E' anche possibile indicare la versione MySQL dalla quale eseguire un comando con /*!40111 MySQL version-specific code */

I sorgenti di MySQL e gli eseguibili (forniti in diverse tipologie di pacchetti a seconda del sistema ospite) sono tutti liberamente scaricabili dal sito MySQL.
MySQL adotta la politica della doppia licenza. Per tutti coloro che soddisfano la GNU GPL l'utilizzo di MySQL e' gratuito, per chi non soddisfa i requisiti della GPL la licenza e' a pagamento. E' inoltre possibile acquistare il supporto al prodotto (MySQL Network).
Anche senza adottare la licenza GPL i costi delle licenze commerciali e del supporto per MySQL sono relativamente limitati.

Stored Procedures

MySQL, dalla versione 5.0, supporta le Stored Routine ovvero un SQL procedurale analogo alle Stored Procedures di Oracle. Le differenze sintattiche tra il PL/SQL di Oracle e MySQL sono notevoli:

La semantica e' abbastanza simile a quella Oracle (ma cosa significa semantica?). Una cosa che manca, ma che ha dato sempre qualche grattacapo ai DBA Oracle, e' l'INVALIDATION. Le Stored Procedure non vengono compilate al momento della creazione ma al momento dell'esecuzione. Questo significa un costo maggiore al momento del primo lancio (poi sono mantenute in cache) ma molti meno problemi nella gestione.
Un'altra differenza e' sulla gestione delle eccezioni, dove MySQL aderisce in modo piu' stretto all'ANSI, con l'utilizzo degli HANDLER.

Anche con MySQL e' possibile definire trigger. Non tutti i tipi di trigger supportati da Oracle sono anche disponibili con MySQL anche se quelli presenti hanno un comportamento analogo. In particolare la gestione dell'invalidation, che e' possibile in Oracle, non puo' essere gestita con MySQL.

La quantita' di funzioni e packages disponibili nel PL/SQL non ha eguali in MySQL. Sono disponibili in MySQL Forge una serie di nuove funzioni... ma la differenza e' di due ordini di grandezza.

Parole, parole, parole, ... forse e' piu' utile un esempio sulla stessa procedura (il benchmark TPC-B) realizzata con il PL/SQL di Oracle e con una Stored Routine di MySQL.

Programmi di supporto

Oracle fornisce un'ampia collezione di tool per le piu' comuni attivita' di amministrazione dei dati. Anche MySQL fornisce strumenti simili. Per rendere pratico il confronto la lista seguente riporta i piu' conosciuti programmi Oracle e come ottenere funzionalita' simili con MySQL:

Installazione ed amministrazione

L'installazione di MySQL e' terribilmente piu' semplice di quella di Oracle. E' sufficiente scaricare dal sito MySQL un RPM (il formato standard dei pacchetti introdotto da Red Hat) e lanciarne l'installazione con rpm -i mysql mysql-server. In pochi minuti si ha un'installazione completa e funzionante di MySQL.
MySQL si comporta anche da listener ed e' quindi immediatamente disponibile per un accesso da rete sulla porta 3306.

E' consigliabile installare da subito anche i programmi client di gestione. Oltre a mysql, che e' l'analogo del sqlplus da installare sul server, MySQL Query Browser e MySQL Admin sono il minimo da installare sulla propria stazione di lavoro. Qualche nota in piu' si trova sul documento Introduzione a MySQL.
A molti DBA Oracle potrebbe piacere anche il TOAD, che e' a pagamento. Sicuramente lo strumento piu' diffuso per l'amministrazione e' il phpMyAdmin che consente la gestione di MySQL con un'interfaccia web semplice e completa.
phpMyAdmin ha molte meno funzionalita' dell'Enterprise Manager... ma e' terribilmente piu' semplice e veloce! In ogni caso si puo' comunque fare tutto da linea di comando con mysql e mysqladmin

Anche l'avvio della base dati e' molto semplice poiche' viene configurato come servizio Unix e richiede solo qualche secondo. I comandi sono:

# service mysql [start|stop]

Generalmente non sono richieste pesanti attivita' amministrative su una base dati MySQL. I principali controlli riguardano l'utilizzo di risorse del sistema (File System e CPU) ed il corretto operare dei backup.
L'Engine InnoDB e' quello piu' complesso e, se usato, richiede una maggiore attenzione nella gestione dei log e per il tuning. A volte puo' essere opportuno deframmentare una tabella con il comando:

ALTER TABLE nome_tabella ENGINE=INNODB;

Configurazione

La configurazione di Oracle non e' banale. Sia che si utilizzi un initXXX o un spfile l'uso delle opzioni possibili e la loro configurazione ottimale richiede molta esperienza.
Con MySQL la configurazione e' piu' semplice. Innanzi tutto MySQL funziona benissimo anche senza alcuna configurazione! Se vi sono situazioni particolari (eg. benchmark, configurazione cluster, ...) la configurazione diventa necessaria ma resta comunque piuttosto semplice.
Oltre ai valori di default le modalita' di impostazione delle variabili di configurazione MySQL sono tre:

MySQL legge le opzioni nell'ordine riportato (quindi l'ultimo ha la precedenza in caso di conflitti).

Ovviamente l'elenco delle opzioni e' molto ampio, ma quanto contenuto nel file d'esempio riportato sopra e' gia' piuttosto completo. Solo a titolo di esempio ed in modo assolutamente indicativo riportiamo i parametri che hanno un impatto maggiore: table_cache simile come effetto a SHARED_POOL_SIZE in Oracle, key_buffer_size simile a DB_BLOCK_BUFFERS, sort_buffer_size simile a SORT_AREA_SIZE, ...

Security

Per MySQL un utente e' identificato da un username e da un host di provenienza. L'host di provenienza e' un'indicazione che su Oracle non e' presente ma che e' molto utile nel definire le autorizzazioni. Ad esempio e' possibile riservare diritti differenti ad un utente quando si collega da un Application Server oppure da un IP riservato ai DBA. Naturalmente e' possibile non indicare una parte: non differenziare per host di provenienza (come farebbe Oracle) oppure utilizzare utenze anonime che provengono da un host o da una rete autorizzata.

A prima vista la gestione delle utenze e dei privilegi su Oracle e MySQL appare molto differente. In realta' le differenze principali sono dovute ai default utilizzati da MySQL durante l'installazione. I database creati dall'installazione (gli schema con la terminologia Oracle) sono 3: mysql (che contiene le tabelle di sistema come la tabella user), information_schema (che contiene le viste del data dictionary) e test (un database di esempio). Al termine dell'installazione e' definito un utente root senza password con tutti i diritti per l'accesso da localhost (per essere precisi gli utenti sono due: uno per localhost e l'altro per hostname). E' inoltre definito un utente anonimo senza password per l'accesso da localhost con con tutti i diritti sul database test.
Per un utilizzo normale tali default sono troppo permissivi e vanno modificati eliminando gli utenti anonimi, impostando le password di root (come per altro riporta la documentazione ufficiale) e, eventualmente eliminando il database test.
Per assegnare una password, o modificarne una presente, il comando e':

# mysql -u root
mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd');
A parte quanto riportato nei paragrafi precedenti le clausole SQL GRANT e REVOKE operano in MySQL in modo corrispondente a quello Oracle.
In MySQL le abilitazioni possono anche essere svolte agendo sulle tabelle mysql.user e mysql.host con normali istruzioni DML dell'SQL. Non va dimenticato il comando FLUSH PRIVILEGES; per sinconizzare le modifiche. Maggiori dettagli sulla gestione dei privilegi si trovano in questo documento.

E' importante sottolineare la differenza presente tra gli SCHEMA Oracle ed i Database MySQL e le modalita' di gestione piu' tipiche per una base dati Enterprise:

Pur consentendo un analogo livello di controllo la "filosofia" MySQL e' molto piu' semplice e non costringe ad aggiornamenti nel caso in cui vengano create nuove tabelle, oggetti, ...

Nella definizione delle utenze, con le versioni piu' recenti di MySQL, e' possibile indicare limiti sulle risorse utilizzabili:

GRANT ALL ON 'jos%'.* TO 'appl_user'@'webServer.domain.it'
    IDENTIFIED BY 'mypass'
    WITH MAX_QUERIES_PER_HOUR 0
    MAX_UPDATES_PER_HOUR 100
    MAX_CONNECTIONS_PER_HOUR 20
    MAX_USER_CONNECTIONS 10;
Si tratta di una funzionalita' simile alla definizione dei profili su Oracle.

La gestione della crittografia delle password, cosi' come la procedura di autenticazione tra client e server in rete, sono state notevolmente migliorate in MySQL (dalla versione 4.1 viene utilizzato un hash di 41 byte) e risultano particolarmente robuste.
E' possibile configurare MySQL per utilizzare l'SSL per il dialogo tra client e server. In questo modo il dialogo (invio degli statement SQL e dati) avviene in modalita' cifrata e non in chiaro. Ovviamente questo comporta la gestione dei certificati (server side) ed un maggior overhead computazionale.
MySQL non fornisce ulteriori funzionalita' (eg. autenticazione LDAP esterna) che Oracle invece fornisce come parte dell'Advanced Network/Security Option.

L'utilizzo della crittografazione consente di mantenere dati non in chiaro sul database.
MySQL offre diverse funzioni di crittografazione dei dati. Le funzioni AES_ENCRYPT() e AES_DECRYPT(), con la chiave a 128 bit per default, sono quelle con maggior sicurezza per la crittografazione. Inoltre MySQL fornisce l'Engine ARCHIVE che mantiene i dati in formato compresso (e quindi non immediatamente leggibile) e pubblica le API per l'eventuale creazione di Engine con modalita' e formati di memorizzazione definiti dal programmatore.

Di default MySQL effettua un logging molto modesto limitandosi a riportare le segnalazioni sui principali eventi nel file hostname.err Ma e' possibile attivare ulteriori livelli di logging:

In MySQL non esiste un AUDIT paragonabile a quello di Oracle; tuttavia sono possibili diverse alternative.
Con MySQL e' possibile realizzare efficienti e completi log applicativi con trigger e routine. L'utilizzo dell'Engine MyISAM o CSV rende semplice la creazione di log applicativi completi poiche' si tratta di Engine non influenzati da eventuali rollback.
Dalla versione 5.1 di MySQL verra' introdotta la possibilita' di avere i log in forma tabellare, consentendo quindi un'analisi dei log in SQL come avviene in Oracle con l'auditing.
Anche se e' ancora definito come release alfa MySQL Proxy e' un ottimo tool per controllare, analizzare, filtrare, ... gli statement SQL tra i client ed il server. Dal punto di vista tecnico e' un proxy cui i client si collegano e che a sua volta si connette al server. Nella configurazione di default si comporta in modo trasparente ma e' possibile programmarlo (con il potente linguaggio Lua) per trattare gli statement SQL. Naturalmente l'utilizzo non e' limitato all'auditing ma puo' essere utilizzato come Load Balancer, per il query filtering, ...

L'aggiornamento delle versioni ed il rilascio di patch e' costante per MySQL. Vengono indicati in modo preciso gli eventuali security fix. Gli aggiornamenti sono pubblicamente accessibili senza oneri aggiuntivi. Con i programmi di supporto a pagamento (MySQL Network) vengono offerti servizi di aggiornamento ed Advisor.

Architettura

Qui le differenze tra MySQL ed Oracle sono tante!

mysqld e' il processo multithreaded che fa tutto. Ascolta su una porta socket, lancia i thread necessari alle sessioni utente, effettua il parsing e l'ottimizzazione degli statement SQL. Per ogni sessione utente MySQL viene lanciato un thread/processo (come in Oracle) che si occupa del parsing dell'SQL e dell'accesso ai dati.
Non esistono quindi processi di background distinti come avviene in Oracle (eg. pmon, smon, lgwr, ...). Non esiste una SGA perche' la memoria e' gestita direttamente dai thread tuttavia, come con Oracle, database significativi e ben configurati hanno bisogno di una buona quantita' di memoria disponibile per essere efficienti.
Per fare un esempio di una situazione reale con 20 utenti connessi in una configurazione di default: con MySQL sara' presente un solo processo con 20 thread interni dedicati alle connessioni; con Oracle vi saranno una quindicina di processi di sistema, un processo listener, i 20 processi dedicati a ciascuna connessione, una o piu' allocazioni di shared memory, qualche centinaio di semafori, ...

Oracle MySQL

Con MySQL non esiste il concetto di istanza e non vi e' un listener separato. Quindi vi e' una sola "istanza" attiva in ascolto sulla porta 3306. Tipicamente applicazioni differenti utilizzano database differenti (che corrispondono agli schema in Oracle).
Naturalmente e' possibile modificare i default ed effettuare installazioni multiple di MySQL, ma non e' una configurazione tipicamente utilizzata.

Ogni database in MySQL corrisponde ad una directory nel file system riservato ai dati. Alla creazione di una tabella viene creato un file tabella.frm che ne contiene la descrizione e, a seconda del tipo di Engine utilizzato, eventuali altri file che mantengono dati ed indici. Il data dictionary e' implementato con alcune semplici tabelle nel database mysql ed information_schema.
Con Oracle la parte di accesso ai dati e' un componente fondamentale del motore mentre con MySQL e' invece separato (e lo sara' sempre piu' nelle prossime versioni). E' quindi possibile sfruttare le caratteristiche dei diversi Engine disponibili o, in casi molto particolari, svilupparne di nuovi! La tabella seguente e' volutamente incompleta ma riporta gli Engine piu' interessanti per un DBA Oracle:

EngineDescrizione
MyISAMEngine di default. Molto veloce e leggero. Consente la creazione di indici FULLTEXT. Non ha il supporto delle transazioni.
I dati sono mantenuti su file ISAM (un file per i dati .MYD ed uno per gli indici ..MYI).
InnoDB Consente la gestione completa delle trasazioni con le proprieta' ACID. Adatto a tutte le applicazioni che richiedono una forte trasazionalita' e la sicurezza dei dati.
I dati vengono mantenuti su un datafile ibdataX (partizionabile dalla 5.1) e protetti con log ib_logfileX (analoghi ai redo log/archived log di Oracle).
Memory Molto utile per dati temporanei ed elaborazioni in sequenza.
I dati sono mantenuti in memoria.
NDBCluster E' l'Engine che supporta il cluster Active-Active di MySQL.
I dati vengono distribuiti tra tutti i nodi che compongono il cluster e sono mantenuti, principalmente, in memoria.
Archive Per la gestione di grosse moli di dati o per la storicizzazione.
I dati sono mantenuti in forma compressa sul file system.
CSV Un Engine molto semplice ma anche comodo per la conversione dei dati.
I dati sono mantenuti su file in formato testo (CSV: Comma Separated Values).
Federated Consente di accedere a tabelle presenti su un sistema remoto. Si tratta di un accesso simile a quello presente in Oracle con i database link (ma con meno funzionalita').
I dati sono mantenuti sul sistema remoto.

Dal punto di vista architetturale l'Engine piu' simile ad Oracle e' l'InnoDB. Quindi lo descriviamo un poco piu' degli altri Engine.
Con InnoDB non sono presenti le complesse possibilita' di gestione dello storage disponibili con Oracle (vi e' una sola tablespace o una tablespace per tabella), il formato delle tabelle e' sempre clustered sulla primary key, non sono disponibili le diverse opzioni di preallocazione degli spazi (eg. INITIAL, MINFREE, ...), ...
Con InnoDB tutte le transazioni vengono gestite in modalita' ACID, analogo all'SCN (System Change Number) in Oracle e' LSN (log sequence number) in InnoDB, sono disponibili e gestiti i referential constraint (anche se con logiche un poco diverse), ...
Lo spazio utilizzato dal file InnoDB non diminuisce mai. Non esistono comandi di shrink o simili. Qualsiasi operazione sulle tabelle (delete, truncate, drop) libera spazio che resta disponibile all'Engine ma non puo' venir rilascato al sistema operativo.

Clustering

Con l'Engine NDB vengono realizzati cluster MySQL Active-Active cosi' come avviene con la configurazione RAC di Oracle. Tuttavia vi sono notevoli differenze dal punto di vista architetturale tra le due soluzioni.
Con Oracle vengono acceduti dischi condivisi contemporaneamente da tutte le istanze del cluster. Particolari meccanismi di locking distribuito e di cache fusion consentono di avere il massimo delle prestazioni.
Con MySQL la gestione dei dati e' a carico dell'Engine NDB che utilizza dischi locali ma soprattutto la memoria per avere i dati sempre disponibili. I diversi processi NDB si scambiano modifiche ed aggiornamenti via rete.

Oracle
RAC
MySQL
NDB

La configurazione di MySQL e di Oracle con cluster Active-Passive a livello di sistema operativo non presenta invece differenze significative. Dati e configurazioni vanno posti su dischi associati al servizio cluster, mentre l'installazione del motore puo' essere mantenuta sui dischi di sistema (tipico su MySQL) o su un file system a parte (tipico su Oracle). Molti prodotti di cluster forniscono gia' script o agenti predisposti per la clusterizzazione dei due RDBMS.

Replication

L'opzione Oracle Active Data Guard fornisce da moltissimo tempo e con un'elevatissima affidabilita' la soluzione per il Disaster Recovery mantenendo istanze identiche all'ambiente di produzione.
MySQL permette, in modo semplice ed efficiente, la replicazione di una base dati.

Oracle
Data Guard
MySQL
Replication

Anche se le due figure precedenti sembrano molto simili le differenze sono notevoli. La replicazione MySQL e' statement based mentre quella Oracle block based!
Questo vuol dire che con Oracle Primary e Standby sono identici bit per bit mentre con MySQL Master e Slave hanno gli stessi dati ma strutture diverse (ed a volte completamente diverse, come nel caso di utilizzo di Engine differenti).
Su Oracle e' disponibile l'Option Active Dataguard che consente di utilizzare in lettura il database di Standby. Con MySQL gli slave sono sempre disponibili (anche in scrittura se non si imposta il read-only).

La soluzione Oracle Data Guard e' utilizzata soprattutto per il Disaster Recovery... La replicazione su MySQL e' sfruttata anche per disporre di un numero elevato di server su cui eseguire statement di SELECT o per backup. Possono essere facilmente effettuare centinaia di repliche di una base dati MySQL permettendo una notevole scalabilita' orizzontale (per le operazioni in sola lettura).

Programmazione

Con entrambe le basi dati e' fortemente consigliabile utilizzare interattivamente l'SQL per controllare le prestazioni degli statement utilizzati nei programmi. E' opportuno anche utilizzare l'EXPLAIN per controllare il percorso scelto dall'ottimizzatore.

Con i parametri di default MySQL e' molto piu' permissivo di Oracle dal punto di vista sintattico: effettua in modo automatico casting, troncamenti ed assegnazione di valori di default, eventualmente segnalando un warning. Ad esempio select 6 + 'pirla'; restituisce "6" (giustamente?!). I warning e gli errori possono essere visualizzati con il comando SHOW WARNINGS;.

A MySQL si accede tipicamente con una connessione ODBC o JDBC. I driver, chiamati MySQL Connector, sono molto efficienti e sono disponibili per i principali linguaggi di programmazione.
Dal punto di vista funzionale non vi sono differenze significative tra MySQL ed Oracle.
Il tempo richiesto per la connessione ad un DB MySQL e' notevolmente inferiore a quanto richiesto per una connessione ad Oracle. Con Oracle l'utilizzo del connection pooling e' quasi un obbligo per applicazioni web mentre con MySQL l'esigenza e' meno sentita.

E' possibile sviluppare programmi in C utilizzando le API C di MySQL come in questo programma di esempio che, tra le altre cose, consente l'uso dei prepared statement (molto efficienti in MySQL come in Oracle).
Nella programmazione in C rispetto ad Oracle vi sono due differenze fondamentali: si tratta di API C e non di Embedded SQL (quindi non vi e' un precompilatore), determinare i parametri per la corretta compilazione con MySQL e' facile: basta lanciare lo script mysql_config.

Quando si scrivono programmi batch e' possibile compilarli in modalita' Embedded. In pratica il motore MySQL viene incluso nell'eseguibile. Qualcosa di simile si poteva fare con Oracle compilando in modalita' SingleTask (anche se l'istanza andava comunque attivata a parte).

Compatibilita' Oracle 100%

In questo paragrafo vengono riassunti i comandi e le opzioni che rendono il comportamento di MySQL il piu' vicino possibile a quello di Oracle. Naturalmente raggiungere il 100% di compatibilita' non e' possibile, e neanche ragionevole, ma... il titolo mi piaceva!


SET GLOBAL sql_mode = ORACLE;
In questo modo MySQL definisce i parametri PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER. Insomma imita Oracle utilizzando || come concatenazione e non come OR, ... Le opzioni che e' possibile impostare con sql_mode sono parecchie, e' quindi possibile far accettare all'interprete SQL di MySQL sintassi differenti.

Ma il punto piu' importante e' sicuramente l'utilizzo delle transazioni. Per una gestione completa delle transazioni con MySQL deve essere utilizzato l'Engine InnoDB. L'Engine puo' essere specificato al momento di creazione delle tabelle, ma puo' anche essere definito come Engine di default:


SET storage_engine=INNODB;
Inoltre Oracle utilizza l'isolation level READ COMMITTED (altre modalita' sono configurabili ma utilizzate di rado). Il default di MySQL e' piu' restrittivo e quindi va modificato con il comando:

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
Gli utenti Oracle sono abituati ad effettuare il COMMIT esplicito e a ricevere errori e warning. Impostando:

SET AUTOCOMMIT=0;
SET SQL_WARNINGS=1;
anche su MySQL dovranno eseguire il commit in modo esplicito (di default MySQL effettua il commit implicito su ogni statement SQL).
Con questi settaggi il comportamento di MySQL e' molto vicino a quello di Oracle (eg ACID, row level locking, deadlock detection, ...) anche se alcune cose sono necessariamente differenti (eg. Error Messages).

Le utenze di default di MySQL sono differenti da quelle di Oracle, anche se quanto segue e' banale...


GRANT ALL ON *.* TO 'sys'@'%' IDENTIFIED BY 'change_on_install' WITH GRANT OPTION;
GRANT ALL ON *.* TO 'system'@'%' IDENTIFIED BY 'manager' WITH GRANT OPTION;
GRANT USAGE ON SCOTT.* TO 'scott'@'%'IDENTIFIED BY 'tiger' ;
cosi' si hanno gli utenti cui si e' abituati con Oracle e non solo root che sembra (ma non e') l'utente di amministrazione di un sistema operativo Unix.

Avendo ora l'avvertenza di utilizzare i database di MySQL come gli schema di Oracle abbiamo oggettivamente poche differenze tra i due database!

Convertire una base dati da Oracle a MySQL e' un'attivita' che richiede diversi passi. Innanzi tutto va disegnata la nuova base dati con datatype corrispondenti a quelli Oracle. Per mantenere la stessa tipologia di gestione delle transazioni deve essere utilizzato l'Engine InnoDB. Quindi vanno preparati programmi di scarico/carico (eg. sqlplus+LOAD).
In realta' conviene utilizzare MySQL Migration Toolkit, un tool di conversione fornito da MySQL, e sfruttare anche l'Engine MyISAM. In questo modo la conversione e' veloce e si sfruttano appieno le funzionalita' di MySQL.

Con quanto visto in questo capitolo e' possibile rendere MySQL molto vicino all'RDBMS Oracle. Ma siete sicuri di volerlo fare? I due DB sono diversi ed hanno funzionalita' differenti. Cercare di renderli simili in ogni aspetto introduce anche limitazioni e non solo vantaggi.

Gateway

Se si utilizzano entrambe MySQL ed Oracle sulle stesse applicazioni sono sicuramente necessari conversioni, caricamenti, ... In tali situazioni il Migration Toolkit e lo statement SQL LOAD DATA INFILE descritti precedentemente sono gli strumenti piu' utili ed utilizzati.
Tuttavia nel caso in cui si voglia vedere una tabella MySQL come se fosse una tabella Oracle e' possibile sfruttare gli Heterogeneous Services di Oracle. A differenza dei Transparent Gateway non vengono effettuate conversioni della sintassi SQL e, a volte, e' necessario qualche trucco quindi... Auguri!

Evoluzione e futuro

Come per tutti i prodotti vivi l'evoluzione su Oracle e MySQL e' continua. L'evoluzione di MySQL, sopratutto all'inizio, ha seguito piu' le necessita' degli sviluppatori che l'aderenza a standard o la compatibilita'.
La versione 3.23 (2001) ha introdotto l'Engine MyISAM e (3.23.34) InnoDB e' ha conosciuto una diffusione fortissima sopratutto nelle architetture LAMP. Le union sono apparse nella 4.0, le subquery nella 4.1. La versione 5.0 di MySQL ha introdotto viste, stored procedures, trigger, data dictionary, ANSI SQL:2003, database link... non e' poco! Nella 5.1 e' presente il partitioning ed una gestione piu' completa del clustering e del logging. La versione 5.2 ha introdotto nuovi Engine, la versione 5.4 ha aumentato la scalabilita' su sistemi SMP; entrambe le versioni sono pero' rimaste solo Beta version; la 6.0 e' addirittura sparita completamente... La 5.5 ha come Engine di default InnoDB 1.1 (con molteplici ottimizzazioni su forti cariche transazionali) ed introduce la modalita' di replicazione semisincrona.

Anche Oracle introduce continuamente nuove funzionalita' (N.d.A. 11gR2) ma l'acquisizione di Innobase (Ottobre 2005) parla chiaro sull'attenzione rivolta al mondo Open Source da parte della Oracle Corporation stessa! (N.d.A. in seguito MySQL AB e' stata acquisita da SUN e questa a sua volta da Oracle!)

Nella versione 5.6, gia' disponibile come RC [NdE dal 5 febbraio 2013 disponibile in produzione], sono presenti: l'accesso alla Host Cache via SQL, full text search con InnoDB, diversi miglioramenti sulla scalabilita', fractional seconds, ...

La versione 5.7 e' probabilmente la versione piu' diffusa con molte nuove funzionalita': performance schema, JSON datatype, InnoDB Cluster, ...

La versione 8.0 presenta molteplici nuove features (eg. CTE, window functions) ma anche una serie di incompatibilita' e differenze con la versione precedente (Query Cache, MyISAM partitioning, ...).


Titolo: MySQL 4 Oracle DBAs
Livello: Avanzato (3/5)
Data: 1 Novembre 2005
Versione: 1.1.0 - 14 Febbraio 2019
Autore: mail [AT] meo.bogliolo.name