Här är ett mer komplett svar med avseende på InnoDB. Det är lite av en lång process, men kan vara värt ansträngningen.
Tänk på att /var/lib/mysql/ibdata1
är den mest trafikerade filen i InnoDB-infrastrukturen. Den innehåller normalt sex typer av information:
- Tabelldata
- Tabellindex
- MVCC (Multiversioning Concurrency Control)
Data
- Återställande segment
- Ångra mellanslag
- Tabellmetadata (Data Dictionary)
- Dubbel skrivbuffert (bakgrundsskrivning för att förhindra beroende av OS-cache)
- Infoga buffert (hanterar ändringar av icke-unika sekundära index)
- Se
Bildrepresentation av ibdata1
InnoDB-arkitektur
Många människor skapar flera ibdata
filer som hoppas på bättre diskutrymmeshantering och prestanda, men den uppfattningen är felaktig.
Kan jag köra OPTIMERA TABELL
?
Tyvärr kör OPTIMERA TABELL
mot en InnoDB-tabell lagrad i den delade tabellutrymmesfilen ibdata1
gör två saker:
- Gör tabellens data och index sammanhängande inuti
ibdata1
- Gör
ibdata1
växa eftersom de sammanhängande data- och indexsidorna läggs till tillibdata1
Du kan dock separera tabelldata och tabellindex från ibdata1
och hantera dem självständigt.
Kan jag köra OPTIMERA TABELL
med innodb_file_per_table
?
Anta att du skulle lägga till innodb_file_per_table
till /etc/my.cnf (my.ini)
. Kan du då bara köra OPTIMERA TABELL
på alla InnoDB-tabeller?
Goda nyheter :När du kör OPTIMERA TABELL
med innodb_file_per_table
aktiverat, kommer detta att producera en .ibd
fil för den tabellen. Till exempel, om du har tabellen mydb.mytable
med en datadir för /var/lib/mysql
, kommer det att producera följande:
/var/lib/mysql/mydb/mytable.frm
/var/lib/mysql/mydb/mytable.ibd
.ibd
kommer att innehålla datasidorna och indexsidorna för den tabellen. Bra.
Dåliga nyheter :Allt du har gjort är att extrahera datasidorna och indexsidorna för mydb.mytable
från att bo i ibdata
. Datadictionary-posten för varje tabell, inklusive mydb.mytable
, finns fortfarande kvar i dataordboken (Se bildrepresentation av ibdata1
). DU KAN INTE BARA RADERA ibdata1
VID DENNA PUNKT !!! Observera att ibdata1
har inte krympt alls.
InnoDB Infrastructure Cleanup
För att krympa ibdata1
en gång för alla måste du göra följande:
-
Dump (t.ex. med
mysqldump
) alla databaser till en.sql
textfil (SQLData.sql
används nedan) -
Släpp alla databaser (förutom
mysql
ochinformationsschema
) VARNING :Som en försiktighetsåtgärd, kör det här skriptet för att vara helt säker på att du har alla användarbidrag på plats:mkdir /var/lib/mysql_grants cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/. chown -R mysql:mysql /var/lib/mysql_grants
-
Logga in på mysql och kör
SET GLOBAL innodb_fast_shutdown =0;
(Detta kommer att ta bort alla återstående transaktionsändringar frånib_logfile0
ochib_logfile1
) -
Stäng av MySQL
-
Lägg till följande rader i
/etc/my.cnf
(ellermy.ini
på Windows)[mysqld] innodb_file_per_table innodb_flush_method=O_DIRECT innodb_log_file_size=1G innodb_buffer_pool_size=4G
(Sidenot:Oavsett vilken uppsättning du har för
innodb_buffer_pool_size
, se till attinnodb_log_file_size
är 25 % avinnodb_buffer_pool_size
.Även:
innodb_flush_method=O_DIRECT
är inte tillgängligt på Windows) -
Ta bort
ibdata*
ochib_logfile*
, Alternativt kan du ta bort alla mappar i/var/lib/mysql
, förutom/var/lib/mysql/mysql
. -
Starta MySQL (Detta kommer att återskapa
ibdata1
[10 MB som standard] ochib_logfile0
ochib_logfile1
vid 1G vardera). -
Importera
SQLData.sql
Nu, ibdata1
kommer fortfarande att växa men bara innehålla tabellmetadata eftersom varje InnoDB-tabell kommer att existera utanför ibdata1
. ibdata1
kommer inte längre att innehålla InnoDB-data och index för andra tabeller.
Anta till exempel att du har en InnoDB-tabell som heter mydb.mytable
. Om du tittar i /var/lib/mysql/mydb
, kommer du att se två filer som representerar tabellen:
mytable.frm
(Storage Engine Header)mytable.ibd
(Tabelldata och index)
Med innodb_file_per_table
alternativet i /etc/my.cnf
, kan du köra OPTIMIZE TABLE mydb.mytable
och filen /var/lib/mysql/mydb/mytable.ibd
kommer faktiskt att krympa.
Jag har gjort detta många gånger under min karriär som MySQL DBA. Första gången jag gjorde det här krympte jag faktiskt 50 GB ibdata1
fil ner till endast 500 MB!
Ge det ett försök. Om du har ytterligare frågor om detta är det bara att fråga. Lita på mig; detta kommer att fungera på kort sikt såväl som på lång sikt.
VARNING
Vid steg 6, om mysql inte kan starta om på grund av mysql
schema börjar släpptes, titta tillbaka på steg 2. Du gjorde den fysiska kopian av mysql
schema. Du kan återställa den enligt följande:
mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql
Gå tillbaka till steg 6 och fortsätt
UPPDATERING 2013-06-04 11:13 EDT
När det gäller inställning av innodb_log_file_size till 25 % av innodb_buffer_pool_size i steg 5 är den generella regeln ganska gammaldags.
Tillbaka den 3 juli 2006
, Percona hade en trevlig artikel varför man ska välja en riktig innodb_log_file_size a> . Senare, den 21 november 2008
, följde Percona upp med en annan artikel om hur man beräknar rätt storlek baserat på maximal arbetsbelastning och behåller en timmes ändringar
.
Jag har sedan dess skrivit inlägg i DBA StackExchange om att beräkna loggstorleken och var jag refererade till dessa två Percona-artiklar.
27 augusti 2012
:Korrekt inställning för 30 GB InnoDB-tabell på server med 48 GB RAM17 januari 2013
:MySQL 5.5 - Innodb - innodb_log_file_size högre än 4 GB tillsammans?
Personligen skulle jag fortfarande gå med 25%-regeln för en initial installation. Sedan, eftersom arbetsbelastningen kan bestämmas mer exakt över tiden i produktionen, kan du ändra storlek loggarna under en underhållscykel på bara några minuter.