La nuova versione MySQL 8.0 [NdE 19 Aprile 2018],
anche se rispetto alla precedente release 5.7
cambia nella numerazione,
e' sopratutto un'evoluzione sulle linee gia' intraprese nelle versioni
precedenti: InnoDB, sicurezza, JSON, ...
Ma ci sono altre importanti novita' nell'SQL come le clausole OVER e WITH o il Data Dictionary
transazionale.
E' stata svolta anche una significativa riorganizzazione e pulizia del codice,
anche se questo e' meno evidente per gli utenti finali che tipicamente
non utilizzano il codice sorgente.
Alcune differenze comunque si notano, ad esempio nella gestione del logging,
nella riduzione degli sql_mode, nell'aumento delle parole riservate, ...
e non mancano alcune incompatibilita'!
In questo documento sono riportati in dettaglio i principali nuovi elementi introdotti dalla versione 8.0 riportando esempi pratici di utilizzo:
Ma le novita' non sono solo queste... continuate a leggere!
Non e' facile in SQL scrivere query per la distinta base, per analizzare strutture gerarchiche o per percorrere un grafo. Le Common Table Expressions (CTE) servono appunto ad effettuare queste ricerche complesse.
La forma piu' semplice delle CTE e' analoga alle SELECT annidate (derived tables):
with engineers as ( select * from employees where dept='Engineering' ) select * from engineers where ... |
select * from ( select * from employees where dept='Engineering' ) as engineers where ... |
Un poco piu' complessa e' la forma ricorsiva che consente di attraversare strutture complesse come alberi o grafi. La sintassi utilizza sempre la clausola WITH per definire il punto di partenza (anchor) ed il collegamento con i dati successivi basato sull'uso ricorsivo della CTE:
with recursive R as ( select anchor_data union [all] select recursive_part from R, ... ) select ...
Vediamo un esempio reale:
Dall'esempio dovrebbe essere chiaro come e' possibile analizzare con l'SQL in maniera ricorsiva insiemi complessi di dati: basta definire i punti di partenza, i collegamenti e... evitare i loop infiniti!
Le Common Table Expressions sono definite nello standard SQL:1999. La documentazione ufficiale riporta maggiori dettagli...
Le Window functions consentono di eseguire operazioni di gruppo associate ad ogni singola riga estratta da una query.
Vediamo un esempio reale:
Dall'esempio dovrebbe essere chiaro come vengono utilizzate le window functions per estrarre dati progressivi, raggruppati, ordinati, ...
Particolarmente conciso e, sopratutto, di facile lettura e' l'SQL per ottenere valori medi:
SELECT variable_value - lag(variable_value) over (order by time_stamp) Bytes_received, time_stamp FROM global_status_history WHERE variable_name='Bytes_received' ORDER BY time_stamp; SELECT iot_time, iot_val, AVG(iot_val) OVER (order by iot_time ROWS between 3 PRECEDING and 3 FOLLOWING) mean_val, AVG(iot_val) OVER (order by iot_time ROWS 6 PRECEDING) pred_val FROM iot_devices; SELECT anno, mese, AVG(fatturato) OVER ( PARTITION BY anno, mese ORDER BY anno, mese ROWS 12 PRECEDING) as fatturato_mensile ...
Oltre alle normali funzioni di gruppo (eg. SUM(), AVG(), ...) sono supportate ulteriori funzioni sulle partizioni: CUME_DIST(), DENSE_RANK(), FIRST_VALUE(), LAG(), LAST_VALUE(), LEAD(), NTH_VALUE(), NTILE(), PERCENT_RANK(), RANK(), ROW_NUMBER().
Le Window functions sono definite nello standard SQL:2003. La documentazione ufficiale riporta maggiori dettagli, tra cui un esempio per determinare il primo valore di un gruppo.
Le novita' piu' significative per il DBA per ottimizzare le performances sono due: i descending indexes e gli invisible indexes. I nomi indicano chiaramente il trattamento da parte dell'ottimizzatore, vediamo quindi un esempio della sintassi per entrambe:
Facile vero?
La gestione delle tabelle temporanee puo' avere impatti significativi sulle performances. Lo Storage Engine TempTable e' il default per le tabelle temporanee e sostituisce lo storico Engine MEMORY.
La scalabilita' verticale e' stata migliorata in modo significativo nella versione 8, le differenze sono evidenti superando 64 sessioni concorrenti.
La gestione dei charset e' stata ottimizzata nella versione 8.0 con il default (utf8mb4) le differenze prestazionali sono significative rispetto alle versioni precedenti.
Infine tra le ottimizzazioni dell'ottimizzatore della otto
[NdA scusate non mi sono trattenuto sull'888]
e' da segnalare l'utilizzo degli istogrammi sulle statistiche delle colonne.
Le altre differenze rispetto alle precedenti versioni sono sopratutto funzionali,
dal punto di vista delle prestazioni MySQL 8.0 e' sostanzalmente in linea con le altre releases.
La versione 8.0 introduce nuove importanti funzioni per il trattamento del data type JSON,
gia' introdotto con la versione 5.7:
->> (inline path), JSON_PRETTY(), JSON_ARRAYAGG(), JSON_OBJECTAGG(), JSON_TABLE(), ...
L'inplace update puo' essere notevolmente piu' performante rispetto alla gestione precedente
che in pratica effettuava una cancellazione ed un nuovo inserimento.
Per sfruttare l'inplace update vanno usate le funzioni: JSON_SET(), JSON_REPLACE(), JSON_REMOVE().
Con l'uscita della versione 8.0 una forte enfasi e' stata data anche all'utilizzo di MySQL
come Document Store grazie all'X Protocol...
ma anche questo era gia' stato introdotto con la 5.7!
E' comunque importante sottolineare che MySQL e' utilizzabile anche con API CRUD
come avviene con i database NoSQL.
Ogni nuova versione di MySQL presenta un aggiornamento significativo sul data dictionary... la versione 8.0 introduce ulteriori novita'.
Il Data dictionary e' ora definito su tabelle transazionali.
La gestione delle DDL e' ora atomica (Atomic DDL).
L'engine InnoDB non ha piu' un proprio distinto data dictionary ma viene utilizzato
il MySQL Data Dictionary (eg. la tabella INNODB_SYS_TABLES e' ora INNODB_TABLES).
Si tratta di variazioni significative ma con un impatto applicativo limitato.
Anche in questa versione vengono aggiunte nuove funzionalita' all'Engine InnoDB.
Sono disponibili le modalita' NOWAIT e SKIP LOCKED negli statement SELECT ... FOR SHARE e SELECT ... FOR UPDATE.
La configurazione dell'AUTO_INCREMENT si mantiene tra riavvi,
in caso di rollback non viene incrementato ed e' stato ottimizzato.
Le tabelle temporanee InnoDB sono create in un tablespace dedicato: ibtmp1.
Sono utilizzate tablespace di undo separate (minimo 2).
Da ultimo ma non come ultimo... la sicurezza. Anche su questo MySQL continua a migliorarsi: ci sono tante piccole differenze e nuove funzionalita' introdotte con la versione 8.0. In questa breve panoramica vediamo: ROLES, password history, validate_password, caching_sha2_password, Redo/Undo Log encryption.
La prima novita' e' la disponibilita' dei ruoli, funzionalita' presente da tempo su molti altri DB. Vediamo la sintassi con degli esempi:
Con la versione 8.0 puo' essere mantenuta la password history, per evitare che un utente utilizzi la stessa password piu' volte. La gestione e' molto semplice e viene effettuata con due parametri (ovviamente da impostare nel file my.cnf):
password_history=6 password_reuse_interval=365
E' anche possibile impostare i valori con l'impostazione di variabili, in modo persistente, oppure indicarli in modo specifico per utente alla creazione/alter di un utente:
Il plugin validate_password e' stato sostituito da un componente
con lo stesso nome.
Anche se trasparente in molti casi, vi sono alcune piccole differenze...
Di default il componente viene installato, ma non su tutte le piattaforme;
se non e' presente bisogna lanciare il comando:
INSTALL COMPONENT 'file://component_validate_password';
Con la versione 8.0 e' possibile impostare la crittografia dei Redo Log e degli Undo Log: basta impostare un parametro a ON [NdA i parametri sono rispettivamente: innodb_redo_log_encrypt, innodb_undo_log_encrypt]. Non e' al momento possibile crittografare il binary log che resta l'unico tipo di file non crittografabile dell'Engine InnoDB [NdA il binary log non e' sempre presente ed e' utilizzato per la replica MySQL].
E' disponibile un nuovo pluging ottimizzato per la crittografia della password:
caching_sha2_password.
Rispetto al plugin sha256_password, introdotto nella 5.7,
mantiene lo stesso livello di sicurezza ma risulta piu' veloce utilizzando un caching.
Nella versione 8.0 il plugin caching_sha2_password e' il default per le nuove installazioni.
Attenzione: se si utilizza il nuovo plugin di autenticazione vanno aggiornate anche
le librerie client alla versione 8.0!
[NdA almeno alla 8.0.4 (che supporta tutte le funzionalita' del plugin) o meglio alla 8.0.11 (prima GA)].
Altrimenti non ci si collega e si hanno errori come:
mysqli_connect(): The server requested authentication method unknown to the client [caching_sha2_password]
Per creare/modificare un'utente assegnando il vecchio plugin di autentificazione,
compatibile con i client delle versioni precenti,
la clausola SQL e'
IDENTIFIED WITH mysql_native_password BY 'XXX';
Le variazioni impattano anche la replica...
nel caso di errore: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection
impostate l'opzione master_ssl=1 nella clausola change master to.
La configurazione del plugin di default si effettua nel my.cnf con [NdA richiede un riavvio]:
default-authentication-plugin=mysql_native_password
Dalla versione 5.7.23 [NdE rilasciata il 27 luglio 2018], le librerie ed i programmi client 5.7 supportano caching_sha2_password e possono cosi' essere utilizzati per collegarsi ad una versione 8.0.
Altre novita' interessanti [NdA aggiornate alla piu' recente versione di produzione: 8.0.13] sono:
INSTALL COMPONENT 'file://component_log_filter_dragnet'; SET GLOBAL log_error_services = 'log_filter_dragnet; log_sink_internal'; SET GLOBAL dragnet.log_error_filter_rules = 'IF err_code == 10559 then drop.';La documentazione ufficiale riporta tutti i dettagli.
Tra le molte variazioni proviamo a ricordare quelle che riteniamo piu' importanti: e' stata rimossa la Query Cache, non sono piu' utilizzabili i relativi parametri; non e' piu' possibile definire utenze con un GRANT: e' necessario usare CREATE USER; sono state rimosse alcune funzioni di crittografia (eg. ENCRYPT, PASSWORD) considerate poco sicure; sono stati rimossi una serie di sql_mode (eg. oracle, postgres) che quindi non possono essere piu' utilizzati; le funzioni Spatial utilizzano ora il prefisso standard ST_ e sono state rimosse tutte le funzioni deprecate in precedenza, le modifiche a fronte di un upgrade sono significative; sono state rimossi dall'INFORMATION_SCHEMA: GLOBAL_VARIABLES, SESSION_VARIABLES, GLOBAL_STATUS, SESSION_STATUS le cui informazioni sono ora disponibili nel Performance Schema; non e' piu' disponibile il partizionamento per l'Engine MyISAM; lo stato Sending data e' stato rimosso e quindi gli statement correnti risultano sempre nello stato Executing [NdA 8.0.17]; ...
La documentazione ufficiale riporta tutti i dettagli delle funzionalita' deprecate o rimosse nella 8.0.
Dalla versione 8.0.34 e' stata deprecato il plugin di autenticazione mysql_native_password.
L'effetto collaterale e' che ogni accesso segnala un warning nel file di log!
Per evitare la segnalazione si puo' usare: set global.log_error_suppression_list='MY-013360';
Oltre alle funzionalita' rimosse gia' riportate nel punto precedente
ed alle differenze nei protocolli di autenticazione,
diversi altri componenti in MySQL 8.0 sono stati implementati in modo differente
rispetto alle precedenti versioni...
in generale non e' supportato il downgrade alla 5.7
sia come strutture binarie sia con un mysqldump.
Un breve riassunto delle funzionalita' introdotte nel tempo si trova su
Introduzione a MySQL.
MySQL e' in costante evoluzione; ecco le funzionalita' introdotte nelle versioni precedenti:
MySQL 5.7,
MySQL 5.6,
MySQL 5.5,
MySQL 5.1,
MySQL 5.0.
Per i piu' curiosi e' anche utile il confronto con un importante fork:
MariaDB 10.2.
Un documento completo con le versioni dei principali software, tra cui MySQL,
e' Il tuo server puzza!
Titolo: MySQL 8.0 - Nuove funzionalita'
Livello: Avanzato
Data: 19 Aprile 2018
Versione: 1.0.5 -
15 Agosto 2023
Autore:
mail [AT] meo.bogliolo.name