InnoDB è uno dei motori di archiviazione più utilizzati in MySQL. Questo motore di archiviazione è noto come motore di archiviazione ad alta affidabilità e prestazioni elevate e i suoi principali vantaggi includono il supporto del blocco a livello di riga, le chiavi esterne e il modello ACID. InnoDB sostituisce MyISAM come motore di archiviazione predefinito da MySQL 5.5, rilasciato nel 2010.
Questo motore di archiviazione può essere incredibilmente performante e potente se ottimizzato correttamente:oggi diamo un'occhiata alle cose che possiamo fare per renderlo al meglio delle sue capacità, ma prima di immergerci in InnoDB, tuttavia, dovremmo capire qual è il suddetto modello ACID.
Cos'è l'ACID e perché è importante?
ACID è un insieme di proprietà delle transazioni del database. L'acronimo si traduce in quattro parole:Atomicità, Consistenza, Isolamento e Durabilità. In breve, queste proprietà garantiscono che le transazioni del database vengano elaborate in modo affidabile e garantiscono la validità dei dati nonostante errori, interruzioni di corrente o problemi simili. Si dice che un sistema di gestione del database che aderisce a questi principi sia un DBMS conforme ad ACID. Ecco come funziona tutto in InnoDB:
- L'atomicità garantisce che le dichiarazioni in una transazione operino come un'unità indivisibile e che i loro effetti siano visti collettivamente o per niente;
- La coerenza è gestita dai meccanismi di registrazione di MySQL che registrano tutte le modifiche al database;
- L'isolamento si riferisce al blocco a livello di riga di InnoDB;
- La durata viene mantenuta anche perché InnoDB mantiene un file di registro che tiene traccia di tutte le modifiche al sistema.
Capire InnoDB
Ora che abbiamo trattato ACID, dovremmo probabilmente guardare come appare InnoDB sotto il cofano. Ecco come appare InnoDB dall'interno (immagine per gentile concessione di Percona):
InnoDB InternalsDall'immagine sopra possiamo vedere chiaramente che InnoDB ne ha alcuni parametri cruciali per la sua performance e questi sono i seguenti:
- Il parametro innodb_data_file_path descrive il tablespace di sistema (il tablespace di sistema è l'area di archiviazione per il dizionario dei dati InnoDB, i buffer di scrittura e modifica doppi e i registri di annullamento). Il parametro rappresenta il file in cui verranno archiviati i dati derivati dalle tabelle InnoDB;
- Il parametro innodb_buffer_pool_size è un buffer di memoria che InnoDB utilizza per memorizzare nella cache i dati e gli indici delle sue tabelle;
- Il parametro innodb_log_file_size rappresenta la dimensione dei file di log di InnoDB;
- Il parametro innodb_log_buffer_size viene utilizzato per scrivere i file di registro su disco;
- Il parametro innodb_flush_log_at_trx_commit controlla l'equilibrio tra la rigorosa conformità ACID e prestazioni più elevate;
- Il parametro innodb_lock_wait_timeout è il tempo in secondi che una transazione InnoDB attende per un blocco di riga prima di rinunciare;
- Il parametro innodb_flush_method definisce il metodo utilizzato per scaricare i dati nei file di dati InnoDB e nei file di registro che possono influenzare il throughput di I/O.
InnoDB memorizza anche i dati dalle sue tabelle in un file chiamato ibdata1 - i log tuttavia sono archiviati in due file separati chiamati ib_logfile0 e ib_logfile1:tutti questi tre file risiedono in /var/lib/mysql directory.
Per rendere InnoDB il più performante possibile, dobbiamo mettere a punto questi parametri e ottimizzarli il più possibile osservando le nostre risorse hardware disponibili.
Ottimizzazione di InnoDB per prestazioni elevate
Per regolare le prestazioni di InnoDB sul tuo hardware, segui questi passaggi:
-
Per estendere automaticamente innodb_data_file_path, specificare l'attributo autoextend nell'impostazione e riavviare il server. Ad esempio:
innodb_data_file_path=ibdata1:10M:autoextend
Quando viene utilizzato il parametro autoextend, la dimensione del file di dati aumenta automaticamente di 8 MB ogni volta che è richiesto lo spazio di tempo. Un nuovo file di dati con estensione automatica può anche essere specificato in questo modo (in questo caso, il nuovo file di dati si chiama ibdata2):
innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend
-
Quando si utilizza InnoDB, il meccanismo principale utilizzato è il pool di buffer. InnoDB fa molto affidamento sul pool di buffer e, come regola pratica, il parametro innodb_buffer_pool_size dovrebbe essere circa dal 60% all'80% della RAM totale disponibile sul server. Tieni presente che dovresti lasciare un po' di RAM anche per i processi in esecuzione nel sistema operativo;
-
Innodb_log_file_size di InnoDB dovrebbe essere impostato il più grande possibile, ma non più grande del necessario. In questo caso, tieni presente che una dimensione del file di registro maggiore è migliore per le prestazioni, ma maggiore è, maggiore è il tempo di ripristino dopo un arresto anomalo. Pertanto, non esiste una soluzione "taglia unica", ma si dice che la dimensione combinata dei file di registro dovrebbe essere sufficientemente grande. Questo aiuta il server MySQL a lavorare regolarmente sull'attività di checkpoint e svuotamento del disco. Ciò consente di risparmiare troppa CPU e I/O del disco e può funzionare senza problemi durante l'ora di punta o l'attività di carico di lavoro elevato. Sebbene l'approccio consigliato sia quello di testarlo e sperimentarlo tu stesso e trovare tu stesso il valore ottimale;
-
Il valore innodb_log_buffer_size deve essere impostato su almeno 16 milioni. Un buffer di registro di grandi dimensioni consente l'esecuzione di transazioni di grandi dimensioni senza la necessità di scrivere il registro su disco prima che le transazioni salvano alcuni I/O del disco;
-
Durante l'ottimizzazione di innodb_flush_log_at_trx_commit, tieni presente che questo parametro accetta tre valori:0, 1 e 2. Con un valore di 1 ottieni la conformità ACID e con valori 0 o 2 ottieni più prestazioni, ma meno affidabilità perché in tal caso le transazioni per le quali i log non sono ancora stati scaricati su disco possono andare perse in un crash;
-
Per impostare innodb_lock_wait_timeout su un valore corretto, tieni presente che questo parametro definisce il tempo in secondi (il valore predefinito è 50) prima emettendo il seguente errore e ripristinando l'istruzione corrente:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
-
In InnoDB sono disponibili più metodi di svuotamento. Per impostazione predefinita, questa impostazione è impostata su "async_unbuffered" su macchine Windows se il valore è impostato su NULL e su "fsync" su macchine Linux. Ecco quali sono i metodi e cosa fanno:
Metodo Flush InnoDB | Scopo |
normale | InnoDB utilizzerà l'I/O asincrono simulato e l'I/O con buffer. |
senza buffer | InnoDB utilizzerà I/O asincrono simulato e I/O non bufferizzato. |
async_unbuffered | InnoDB utilizzerà l'I/O asincrono di Windows e l'I/O senza buffer. Impostazioni predefinite su macchine Windows. |
fsync | InnoDB utilizzerà la funzione fsync() per svuotare i dati ei file di registro. Impostazione predefinita su macchine Linux. |
O_DSYNC | InnoDB utilizzerà O_SYNC per aprire e svuotare i file di registro e la funzione fsync() per svuotare i file di dati. O_DSYNC è più veloce di O_DIRECT, ma i dati possono essere o meno coerenti a causa della latenza o di un arresto anomalo totale. |
nosync | Utilizzato per test interni delle prestazioni - non supportato. |
littlesync | Utilizzato per test interni delle prestazioni - non supportato. |
O_DIRECT | InnoDB utilizzerà O_DIRECT per aprire i file di dati e la funzione fsync() per svuotare sia i dati che i file di registro. Rispetto a O_DSYNC, O_DIRECT è più stabile e più coerente con i dati, ma più lento. La cache del sistema operativo verrà evitata utilizzando questa impostazione:questa impostazione è l'impostazione consigliata su macchine Linux. |
O_DIRECT_NO_FSYNC | InnoDB utilizzerà O_DIRECT durante lo svuotamento dell'I/O - la parte "NO_FSYNC" definisce che la funzione fsync() verrà saltata. |
- Dovresti anche considerare di abilitare l'impostazione innodb_file_per_table. Questo parametro è attivo per impostazione predefinita in MySQL 5.6 e versioni successive. Questo parametro ti solleva dai problemi di gestione relativi alle tabelle InnoDB memorizzandole in file separati ed evitando dizionari principali e tabelle di sistema gonfi. L'abilitazione di questa variabile evita anche di affrontare la complessità del recupero dei dati quando una determinata tabella è danneggiata
- Ora che hai modificato queste impostazioni seguendo le istruzioni descritte sopra, dovresti essere quasi pronto per iniziare! Prima di iniziare a correre, dovresti probabilmente tenere d'occhio il file più trafficato dell'intera infrastruttura InnoDB:ibdata1.
Trattare con ibdata1
Ci sono diverse classi di informazioni memorizzate in ibdata1:
- I dati delle tabelle InnoDB;
- Gli indici delle tabelle InnoDB;
- Metadati della tabella InnoDB;
- Dati MVCC (Multiversion Concurrency Control);
- Il buffer doublewrite - tale buffer consente a InnoDB di recuperare da pagine scritte a metà. Lo scopo di tale buffer è prevenire il danneggiamento dei dati;
- Il buffer di inserimento:tale buffer viene utilizzato da InnoDB per memorizzare nel buffer gli aggiornamenti sulla stessa pagina in modo che possano essere eseguiti contemporaneamente e non uno dopo l'altro.
Quando si ha a che fare con grandi set di dati, il file ibdata1 può diventare estremamente grande e questo può essere il fulcro di un problema molto frustrante:il file può solo crescere e, per impostazione predefinita, non può ridursi. Puoi chiudere MySQL ed eliminare questo file, ma questo non è raccomandato a meno che tu non sappia cosa stai facendo. Quando viene eliminato, MySQL non funzionerà correttamente poiché il dizionario e le tabelle di sistema sono sparite, quindi la tabella di sistema principale è danneggiata.
Per ridurre ibdata1 una volta per tutte, segui questi passaggi:
- Scarica tutti i dati dai database InnoDB. Puoi usare mysqldump o mysqlpump per questa azione;
- Elimina tutti i database ad eccezione dei database mysql, performance_schema e information_schema;
- Interrompi MySQL;
- Aggiungi quanto segue al tuo file my.cnf:
[mysqld] innodb_file_per_table = 1 innodb_flush_method = O_DIRECT innodb_log_file_size = 25% of innodb_buffer_pool_size innodb_buffer_pool_size = up to 60-80% of available RAM.
- Elimina i file ibdata1 e ib_logfile* (questi verranno ricreati al prossimo riavvio di MySQL);
- Avvia MySQL e ripristina i dati dal dump che hai eseguito prima. Dopo aver eseguito i passaggi sopra descritti, il file ibdata1 continuerà a crescere, ma non conterrà più i dati delle tabelle InnoDB:il file conterrà solo metadati e ogni tabella InnoDB esisterà al di fuori di ibdata1. Ora, se vai nella directory /var/lib/mysql, vedrai due file che rappresentano ogni tabella che hai con il motore InnoDB. I file saranno così:
- demotable.frm
- demotable.ibd
Il file .frm contiene l'intestazione del motore di archiviazione e il file .ibd contiene i dati della tabella e gli indici della tabella.
Prima di implementare le modifiche, assicurati di mettere a punto i parametri in base alla tua infrastruttura. Questi parametri possono creare o interrompere le prestazioni di InnoDB, quindi assicurati di tenerli d'occhio in ogni momento. Ora dovresti essere a posto!
Riepilogo
Per riassumere, l'ottimizzazione delle prestazioni di InnoDB può essere un grande vantaggio se si sviluppano applicazioni che richiedono integrità dei dati e prestazioni elevate allo stesso tempo - InnoDB consente di modificare la quantità di memoria consentita al motore consumo, per modificare la dimensione del file di registro, il metodo di svuotamento utilizzato dal motore e così via:queste modifiche possono far funzionare InnoDB estremamente bene se sono ottimizzate correttamente. Prima di eseguire qualsiasi miglioramento, tuttavia, fai attenzione alle conseguenze delle tue azioni sia sul tuo server che su MySQL.
Come sempre, prima di ottimizzare qualsiasi cosa per le prestazioni, esegui sempre (e testa!) backup in modo da poter ripristinare i dati se necessario e testare sempre eventuali modifiche su un server locale prima di implementare le modifiche in produzione.