Howto: pulire un motore di archiviazione mysql InnoDB?


133

È possibile pulire un motore di archiviazione mysql innodb in modo che non memorizzi i dati dalle tabelle eliminate?

O devo ricostruire un nuovo database ogni volta?


Cosa ti fa pensare che MySQL stia archiviando dati da tabelle cancellate?
Robert Munteanu,

1
Se faccio cadere un sacco di enormi tavoli, i miei file di archiviazione InnoDB non si riducono
Bryan Field

2
@RobertMunteanu: vedi bugs.mysql.com/bug.php?id=1341
Max

Risposte:


351

Ecco una risposta più completa riguardo a InnoDB. È un processo un po 'lungo, ma può valere la pena.

Tieni presente che /var/lib/mysql/ibdata1è il file più occupato nell'infrastruttura InnoDB. Ospita normalmente sei tipi di informazioni:

  • Dati tabella
  • Indici delle tabelle
  • Dati MVCC (Multiversioning Concurrency Control)
    • Segmenti di rollback
    • Annulla spazio
  • Tabella dei metadati (dizionario dei dati)
  • Double Write Buffer (scrittura in background per impedire la dipendenza dalla cache del sistema operativo)
  • Inserisci buffer (gestione delle modifiche agli indici secondari non univoci)
  • Vedi il Pictorial Representation of ibdata1

Architettura di InnoDB

Architettura di InnoDB

Molte persone creano più ibdatafile sperando in una migliore gestione e prestazioni dello spazio su disco, tuttavia questa convinzione è errata.

Posso correre OPTIMIZE TABLE?

Sfortunatamente, l'esecuzione OPTIMIZE TABLEsu una tabella InnoDB memorizzata nel file tablespace condiviso ibdata1fa due cose:

  • Rende i dati e gli indici della tabella contigui all'interno ibdata1
  • Marche ibdata1crescere perché le pagine di dati e indice contigui vengono aggiunti aibdata1

Tuttavia, è possibile separare i dati delle tabelle e gli indici delle tabelle da ibdata1e gestirli in modo indipendente.

Posso correre OPTIMIZE TABLEcon innodb_file_per_table?

Supponiamo che si dovesse aggiungere innodb_file_per_tablea /etc/my.cnf (my.ini). Puoi quindi eseguire solo OPTIMIZE TABLEsu tutte le tabelle InnoDB?

Buone notizie : quando si esegue OPTIMIZE TABLEcon innodb_file_per_tableabilitato, questo produrrà un .ibdfile per quella tabella. Ad esempio, se si dispone di una tabella mydb.mytablecon datadir di /var/lib/mysql, produrrà quanto segue:

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Il .ibdconterrà le pagine di dati e le pagine indice per quel tavolo. Grande.

Cattive notizie : tutto ciò che hai fatto è estrarre le pagine di dati e le pagine di indice mydb.mytabledal vivere ibdata. La voce del dizionario dei dati per ogni tabella, incluso mydb.mytable, rimane ancora nel dizionario dei dati (vedere la rappresentazione grafica di ibdata1 ). NON PUOI ESSERE SOLO ELIMINATO ibdata1A QUESTO PUNTO !!! Si noti che ibdata1non si è affatto ridotto.

Pulizia dell'infrastruttura InnoDB

Per ridurre ibdata1una volta per tutte è necessario effettuare le seguenti operazioni:

  1. Dump (ad es. Con mysqldump) tutti i database in un .sqlfile di testo ( SQLData.sqlutilizzato di seguito)

  2. Elimina tutti i database (eccetto mysqle information_schema) CAVEAT : per precauzione, esegui questo script per assicurarti di disporre di tutte le autorizzazioni utente:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Accedi a mysql ed esegui SET GLOBAL innodb_fast_shutdown = 0;(Questo eliminerà completamente tutte le rimanenti modifiche transazionali da ib_logfile0e ib_logfile1)

  4. Chiudi MySQL

  5. Aggiungi le seguenti righe a /etc/my.cnf(o my.inisu Windows)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (Sidenote: qualunque sia il tuo set innodb_buffer_pool_size, assicurati che innodb_log_file_sizesia il 25% di innodb_buffer_pool_size.

    Inoltre: innodb_flush_method=O_DIRECTnon è disponibile su Windows)

  6. Elimina ibdata*e ib_logfile*, facoltativamente, puoi rimuovere tutte le cartelle in /var/lib/mysql, tranne /var/lib/mysql/mysql.

  7. Avviare MySQL (questo ricrea ibdata1[10 MB per impostazione predefinita] ib_logfile0e ib_logfile1a 1G ciascuno).

  8. Importare SQLData.sql

Ora, ibdata1continuerà a crescere ma conterrà solo metadati di tabella perché ogni tabella InnoDB esisterà al di fuori di ibdata1. ibdata1non conterrà più dati e indici InnoDB per altre tabelle.

Ad esempio, supponiamo di avere una tabella InnoDB denominata mydb.mytable. Se guardi dentro /var/lib/mysql/mydb, vedrai due file che rappresentano la tabella:

  • mytable.frm (Intestazione del motore di archiviazione)
  • mytable.ibd (Dati tabella e indici)

Con l' innodb_file_per_tableopzione in /etc/my.cnf, è possibile eseguire OPTIMIZE TABLE mydb.mytablee il file /var/lib/mysql/mydb/mytable.ibdverrà effettivamente ridotto.

L'ho fatto molte volte nella mia carriera come DBA MySQL. In effetti, la prima volta che l'ho fatto, ho ridotto un file da 50 GB ibdata1 a soli 500 MB!

Provaci. Se hai ulteriori domande su questo, basta chiedere. Fidati di me; questo funzionerà a breve termine e nel lungo periodo.

AVVERTIMENTO

Al passaggio 6, se mysql non è in grado di riavviarsi a causa mysqldell'inizio dello schema rilasciato, tornare al passaggio 2. È stata effettuata la copia fisica dello mysqlschema. Puoi ripristinarlo come segue:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Torna al passaggio 6 e continua

AGGIORNAMENTO 2013-06-04 11:13 EDT

Per quanto riguarda l'impostazione di innodb_log_file_size al 25% di innodb_buffer_pool_size al passaggio 5, questa regola generale è piuttosto vecchia scuola.

Di nuovo July 03, 2006, Percona aveva un bell'articolo sul perché scegliere un innodb_log_file_size corretto . Successivamente, Nov 21, 2008Percona ha seguito un altro articolo su come calcolare la dimensione corretta in base al picco del carico di lavoro mantenendo un'ora di modifiche .

Da allora ho scritto messaggi nello StackExchange di DBA sul calcolo delle dimensioni del registro e su cui ho fatto riferimento a quei due articoli di Percona.

Personalmente, continuerei con la regola del 25% per una configurazione iniziale. Quindi, poiché il carico di lavoro può essere determinato in modo più preciso nel tempo in produzione, è possibile ridimensionare i registri durante un ciclo di manutenzione in pochi minuti.


9
Ho anche usato l'opzione innodb_file_per_table con grande efficacia, avendo 200 database con 200 tabelle ciascuno su un singolo server, sono stato in grado di collegare i database delle differenze su diverse partizioni, quindi usando più buffer IO e mandrini che altrimenti sarebbero stati disponibili :)
Dave Rix,

2
@SeanDowney BTW ricordati di rilanciare innodb_open_tablesse necessario. Il valore predefinito è 300.
RolandoMySQLDBA

2
@ giorgio79 devi impostare l'inserto in blocco su un valore maggiore. Questo è un buon punto. Aggiungerò l'essenza della tua domanda alla mia risposta.
RolandoMySQLDBA

3
Nei sistemi a 32 bit non è consentito un valore di 4 Gb per innodb_buffer_pool_size . Mysql inizierà silenziosamente con innodb disabilitato e le tabelle ripristinate verranno cambiate in myisam. Utilizzare un valore leggermente inferiore per correggerlo.
David

5
Buon Dio. Voglio solo dire che questa è forse una delle migliori risposte che io abbia mai visto in un così bel lavoro, signore. Mi ha aiutato a trovare una soluzione al mio problema quando stavo ottenendo un ERRORE 2013 (HY000) durante l'importazione di 154 g di db. Grazie per l'ottima risposta!
Josh Brown,

4

Il motore InnoDB non memorizza i dati eliminati. Durante l'inserimento e l'eliminazione delle righe, lo spazio inutilizzato viene allocato nei file di archiviazione di InnoDB. Nel tempo, lo spazio complessivo non diminuirà, ma nel tempo lo spazio "cancellato e liberato" verrà automaticamente riutilizzato dal server DB.

È possibile ottimizzare ulteriormente e gestire lo spazio utilizzato dal motore attraverso una riorganizzazione manuale delle tabelle. Per fare ciò, scaricare i dati nelle tabelle interessate utilizzando mysqldump, eliminare le tabelle, riavviare il servizio mysql e quindi ricreare le tabelle dai file di dump.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.