Mysql
 sql >> Database >  >> RDS >> Mysql

Howto:pulire un motore di archiviazione mysql InnoDB?

Ecco una risposta più completa per quanto riguarda 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. Normalmente ospita sei tipi di informazioni:

  • Dati tabella
  • Indici delle tabelle
  • MVCC (Multiversioning Concurrency Control) Dati
    • Segmenti di rollback
    • Annulla spazio
  • Metadati tabella (dizionario dati)
  • Doppio buffer di scrittura (scrittura in background per evitare che si affidi alla memorizzazione nella cache del sistema operativo)
  • Inserisci buffer (gestione delle modifiche agli indici secondari non univoci)
  • Vedi Pictorial Representation of ibdata1

Architettura InnoDB

Molte persone creano più ibdata file che sperano in una migliore gestione e prestazioni dello spazio su disco, tuttavia questa convinzione è sbagliata.

Posso eseguire OPTIMIZE TABLE ?

Sfortunatamente, eseguendo OPTIMIZE TABLE contro una tabella InnoDB archiviata nel file tablespace condiviso ibdata1 fa due cose:

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

Tuttavia, puoi separare i dati delle tabelle e gli indici delle tabelle da ibdata1 e gestirli in autonomia.

Posso eseguire OPTIMIZE TABLE con innodb_file_per_table ?

Supponiamo di dover aggiungere innodb_file_per_table a /etc/my.cnf (my.ini) . Puoi quindi eseguire semplicemente OPTIMIZE TABLE su tutte le tabelle InnoDB?

Buone notizie :Quando esegui OPTIMIZE TABLE con innodb_file_per_table abilitato, questo produrrà un .ibd file per quella tabella. Ad esempio, se hai la tabella mydb.mytable con una datadir di /var/lib/mysql , produrrà quanto segue:

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

Il .ibd conterrà le pagine dati e le pagine indice per quella tabella. Ottimo.

Cattive notizie :Tutto quello che hai fatto è estrarre le pagine dati e le pagine indice di mydb.mytable dal vivere in ibdata . La voce del dizionario dei dati per ogni tabella, incluso mydb.mytable , rimane ancora nel dizionario dei dati (consultare la Rappresentazione pittorica di ibdata1 ). NON PUOI SEMPLICEMENTE ELIMINARE ibdata1 A QUESTO PUNTO!!! Tieni presente che ibdata1 non si è affatto ridotto.

Pulizia dell'infrastruttura InnoDB

Per ridurre ibdata1 una volta per tutte devi fare quanto segue:

  1. Dump (ad esempio, con mysqldump ) tutti i database in un .sql file di testo (SQLData.sql viene utilizzato di seguito)

  2. Elimina tutti i database (tranne mysql e information_schema ) AVVISO :Per precauzione, esegui questo script per assicurarti di avere tutte le autorizzazioni utente in atto:

    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 cancellerà completamente tutte le rimanenti modifiche transazionali da ib_logfile0 e ib_logfile1 )

  4. Spegni MySQL

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

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

    (Nota a margine:qualunque sia il tuo set per innodb_buffer_pool_size , assicurati innodb_log_file_size è il 25% di innodb_buffer_pool_size .

    Inoltre:innodb_flush_method=O_DIRECT non è disponibile su Windows)

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

  7. Avvia MySQL (questo ricreerà ibdata1 [10 MB per impostazione predefinita] e ib_logfile0 e ib_logfile1 a 1G ciascuno).

  8. Importa SQLData.sql

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

Ad esempio, supponiamo di avere una tabella InnoDB denominata mydb.mytable . Se guardi in /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 il innodb_file_per_table opzione in /etc/my.cnf , puoi eseguire OPTIMIZE TABLE mydb.mytable e il file /var/lib/mysql/mydb/mytable.ibd si ridurrà effettivamente.

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

Provaci. Se hai altre domande su questo, chiedi. Fidati di me; questo funzionerà sia a breve che a lungo termine.

AVVISO

Al passaggio 6, se mysql non può riavviarsi a causa di mysql schema begin droppato, guarda indietro al passaggio 2. Hai fatto la copia fisica di mysql schema. 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 04-06-2013 11:13 EDT

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

Torna su July 03, 2006 , Percona ha pubblicato un bell'articolo perché scegliere un corretto innodb_log_file_size . Più tardi, il Nov 21, 2008 , Percona ha proseguito con un altro articolo su come calcolare la dimensione corretta in base al carico di lavoro di picco mantenendo un'ora di modifiche .

Da allora ho scritto post in DBA StackExchange sul calcolo della dimensione del registro e su dove ho fatto riferimento a quei due articoli di Percona.

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