10
Die InnoDB Storage Engine: Konfiguration Die wunderbare Welt von Isotopp Sonntag, 3. Februar 2008 Die InnoDB Storage Engine: Konfiguration Links: Strukturen im Speicher, Rechts: Strukturen auf Disk. Oben: LogStrukturen, Unten: TablespaceStrukturen. Wie eine Transaktion physikalisch organisiert wird Wenn in InnoDB eine neue Transaktion begonnen und erzeugt wird, ist sie ja noch nicht comitted und damit hat die Datenbank gegenüber der Anwendung noch kein Versprechen gemacht. Entsprechend brauchen die Daten aus einer solchen Transaktion auch noch nicht persistent gemacht zu werden. InnoDB versucht, eine Transaktion im Speicher zusammen zu bauen. Dies ist der innodb_log_buffer. Er sollte ausreichend groß gewählt werden, daß eine solche Transaktion in den meisten Fällen im Speicher gehalten werden kann und nicht partiell in ein Redo Log geschrieben werden muß. Eine Größe von 1 MB bis 8 MB ist normal. Wenn die Transaktion comitted wird, muß InnoDB die Speicherseite von der Platte laden, in der der zu ändernde Record enthalten ist und die Änderung im Speicher

Die MySQL InnoDB Storage Engine (Teil 2)

Embed Size (px)

Citation preview

Page 1: Die MySQL InnoDB Storage Engine (Teil 2)

Die InnoDB Storage Engine:Konfiguration

Die wunderbare Welt von Isotopp

Sonntag, 3. Februar 2008Die InnoDB Storage Engine: Konfiguration

Links: Strukturen im Speicher, Rechts: Strukturen auf Disk.

Oben: Log­Strukturen, Unten: Tablespace­Strukturen.

Wie eine Transaktion physikalisch organisiert wird

Wenn  in  InnoDB eine neue Transaktion begonnen und erzeugt wird,  ist sie  ja nochnicht  comitted  und damit  hat  die Datenbank gegenüber  der Anwendung noch  keinVersprechen  gemacht.  Entsprechend  brauchen  die  Daten  aus  einer  solchenTransaktion auch noch nicht persistent gemacht zu werden.

InnoDB  versucht,  eine Transaktion  im Speicher  zusammen  zu  bauen. Dies  ist  derinnodb_log_buffer.  Er  sollte  ausreichend  groß  gewählt  werden,  daß  eine  solcheTransaktion  in  den  meisten  Fällen  im  Speicher  gehalten  werden  kann  und  nichtpartiell in ein Redo Log geschrieben werden muß. Eine Größe von 1 MB bis 8 MB istnormal.

Wenn die Transaktion comitted wird, muß  InnoDB die Speicherseite von der Platteladen,  in der der  zu ändernde Record enthalten  ist  und die Änderung  im Speicher

Page 2: Die MySQL InnoDB Storage Engine (Teil 2)

durchführen ­ die Seite wird im InnoDB Bufferpool gespeichert. Seiten auf der Platteund im InnoDB Bufferpool sind jeweils 16 KB groß, und die innodb_buffer_pool_sizelegt  fest,  wieviel  RAM  als  Cache  für  solche  Seiten  zur  Verfügung  steht.  Diemodifizierte Speicherseite wird aber noch nicht zurück geschrieben. Stattdessen wirddie Transaktion an Ende des aktuellen Redo­Log auf Platte geloggt und die Seite imBufferpool im Speicher als Dirty (= noch zu schreiben) markiert.

Als Dirty markierte Seiten werden in den Tablespace hinaus geschrieben, wenn einervon drei Fällen eintritt:

1. Das  Redo­Log,  das  als  Ring  Puffer  organisiert  ist,  ist  voll.  Um  zusätzlichenPlatz zu gewinnen müssen als Dirty markierte Seiten in Redo­Log Reihenfolgeherausgeschrieben  werden,  sodaß  der  hintere  Zeiger  des  Redo­LogRingpuffers nach vorne verschoben werden kann und so ausreichend Platz imRedo­Log geschaffen wird. Diese Situation nennt man einen  Innodb_log_waitund sie wird im gleichnamigen Statuscounter registriert.

2. InnoDB benötigt  für  irgendwelche Aufgaben  im Bufferpool eine Speicherseite,aber  findet  keine,  die  frei  ist.  Normalerweise  kann  eine  solche  Seite  freigemacht werden, indem man irgendeine Seite aussucht, die nicht Dirty ist undsie  freigibt:  Wenn  eine  Seite  nicht  dirty  ist,  bedeutet  daß,  daß  ihr  Inhaltirgendwo auf der Platte zum Neu laden rumsteht. Wenn aber ausschließlich alsDirty markierte Seiten im Bufferpool stehen, geht das nicht und es müssen ersteinmal  Seiten  auf  Platte  geschrieben  werden,  damit  Platz  im  Bufferpoolgeschaffen  werden  kann.  Diese  Situation  nennt  man  einenInnodb_buffer_pool_wait_free  und  sie  wird  im  gleichnamigen  Statuscounterregistriert.  InnoDB  versucht  diese  Situation  zu  vermeiden:  Wenn  mehr  alsinnodb_max_dirty_pages_pct Prozent viele Seiten als Dirty markiert sind, wirdein  Checkpoint  erzwungen  und  die  als  Dirty  markierten  Seiten  werdenherausgeschrieben.

3. InnoDB fühlt sich unterbeschäftigt und beginnt im Sekundentakt damit, Batchesvon  jeweils  64  als Dirty markierten Seiten  auf  die Platte  zu  schubsen. DieseSituation  ist  normal  und  wird  nicht  besonders  registriert  (dreht  aber  wie  allediese Schreibzugriffe natürlich Innodb_pages_written hoch).

Relevante Konfigurationseinträge in der my.cnf:CODE:# Globaler Puffer zum Zusammenbau 

# von Transaktionen vor dem Commit

innodb_log_buffer_size = 8M

# Größe des InnoDB Buffer Pools

#   etwa 70­80% des Hauptspeichers,

#   auf einer Maschine mit 4G RAM

#   also etwa 3G

#

# (/etc/sysctl.conf: vm.swappiness = 0!)

innodb_buffer_pool_size = 3072M

# Anzahl der InnoDB Bufferpool Seiten

# die Drity sein dürfen bevor ein

# Checkpoint erzwungen wird

#

# Default = 90, ok

innodb_max_dirty_pages_pct = 90

Relevante Zähler in SHOW GLOBAL STATUS:CODE:# Statuszähler für das Event "Redo Log voll"

Innodb_log_waits 

Page 3: Die MySQL InnoDB Storage Engine (Teil 2)

# Statuszähler für das Event "Keine Seite# im Bufferpool frei"Innodb_buffer_pool_wait_free

Eine sinnvolle Größe für das Redo­Log wählen

Ein Write­Burst kann durch das Redo­Log "in der Zeit gestreckt" und so abgeflacht werden. Die zuleistende Arbeit ­ die Fläche unter der Kurve ­ ist jedoch (nahezu) gleich.

Das  Redo­Log  loggt  Transaktionen  und  die  Einträge  im  Log  sind  proportional  zurGröße der Transaktion, denn es werden Rows geloggt, keine Pages. Der Sinn desLogs  ist  es,  das  Zurückschreiben  der  16KB  großen  Seiten  in  den  Tablespaceverzögern  zu  können: Vielfach  ist  es  so,  daß  in  einer Speicherseite mehr  als  eineRow abgelegt wird und daß mehrere zeitlich eng beeinander liegende TransaktionenDaten in Rows ändern, die in derselben Page liegen, oder daß eine Row wieder undwieder  überschrieben  wird.  Durch  das  Schreiben  ins  Redo­Log  werden  dieseÄnderungen  alle  persistent  gemacht,  aber  die  Schreibzugriffe  können  als  lineareWrites ohne Seeks recht schnell abgewickelt werden. Die Seeks, die beim Schreibenin  den  Tablespace  unvermeidlich  auftreten  würden,  können  so  verzögert  undminimiert werden.

Normalerweise sollte das Redo­Log immer groß genug sein und niemals voll laufen.Entsprechend  sollte  Innodb_log_waits  immer  0  sein  oder  zumindest  sich  nichtbewegen, wenn man zwei Mal in Folge den Wert des Statuscounters abruft. Hat manregelmäßig  Innodb_log_wait­Events, kann eine von zwei Situationen vorliegen: DerServer hat Write­Bursts, die größer sind als das aktuelle Redo­Log ­ das Redo­Logist  zu  klein  und muß  vergrößert  werden. Oder  der  Server  hat  dauerhaft  eine  sehrgroße Schreiblast und das Redo­Log würde überlaufen, egal wie groß es  ist. Dannbraucht der Server mehr Spindeln, um schneller schreiben zu können oder die Datenmüssen partitioniert und auf mehrere Server verteilt werden.

Das Redo­Log besteht per Default aus zwei Dateien (innodb_log_files_in_group), diejeweils 5 MB groß sind (innodb_log_file_size), ist also 10 MB groß. Dies ist zu klein.Idealerweise sollte es aus zwei Dateien bestehen, die jeweils zwischen 64 und 256MB groß sind, also 128 MB bis 512 MB groß sein. Es kann nicht größer sein als 4096MB = 4 GB, auch nicht auf einer Maschine mit 64 Bit Architektur.

Früher  (vor MySQL 5.0) war es einmal wesentlich, das Redo­Log nicht zu groß zu

Page 4: Die MySQL InnoDB Storage Engine (Teil 2)

machen: Wenn  der  Server  crashte,  ging  InnoDB  in  die  Log  Recovery  Phase  undmußte  diese  erst  abarbeiten  bevor  der  Server  wieder  Verbindungen  annahm.  SeitMySQL  5.0  ist  das  nicht  mehr  so:  Die  Log  Recovery  Phase  kann  vom  Server  imHintergrund  abgearbeitet  werden,  sodaß  die  Größe  des  Redo­Logs  nicht  mehrbestimmend für die Dauer der Server­Recovery ist.

Ändert  man  diese  Variable  wenn  ib_logfile0  und  ib_logfile1  schon  existieren,  wirdInnoDB  sich  weigern  zu  starten  und  im  Error­Log  des  Servers  eine  Meldunghinterlassen, die  im wesentlichen sagt,  daß die Größe von vorgefundenen Logfilesnicht mit der Größe der konfigurierten Logfiles übereinstimmt.Um  die Größe  des Redo­Logs  zu  ändern muß  der  Server  runtergefahren werden,danach  kontrolliert  werden,  daß  der  Shutdown  sauber  war  und  daß  keinServerprozeß mehr  läuft. Dann  kann man die  existierenden  ib_logfile?­Dateien  zurSeite moven und den Wert der Konfigurationsvariablen ändern, um schließlich denServer zu starten.  InnoDB wird nun Meldungen über neu angelegte Logfiles  in dasError­Log  schreiben  und  die  Files  generieren.  Ist  der  Server  wieder  online  undbetriebsbereit, kann man die alten ib_logfile?­Dateien löschen.

Relevante Konfigurationseinträge in der my.cnf:CODE:# Anzahl der ib_logfile?

innodb_log_files_in_group = 2

# Größe eines ib_logfile?innodb_log_file_size = 256M

Wie InnoDB die Datendateien ablegt

Wie  bereits  in  dem  ersten  Artikel  dieser  Reihe  angedeutet  hat  InnoDB  zweiverschiedene  Betriebsarten,  in  denen  es  seine  Daten  unterschiedlich  organisiert:Wenn  die  Konfigurationsvariable  innodb_file_per_table  =  0  gesetzt  ist,  werden  dieDaten  in  einem  oder  mehreren  ibdata­Tablespacefiles  abgelegt.  Wenn  dieinnodb_file_per_table  =  1  gesetzt  ist,  wird  stattdessen  für  jede  Tabelle  neben  der.frm­Datei für die Tabelle ein .ibd­File angelegt, das die Daten enthält.

Die  Tablespace­Files  werden,  wenn  ihre  Namen  nicht  als  absolute  Pfadnamenangegeben werden, in innodb_data_home_dir angelegt. Ist auch diese Variable leer,wird als Default  datadir  angenommen. Der Default­String  für  innodb_data_file_pathist "ibdata1:10M:autoextend".

In  den  meisten  Default­Installationen  bedindet  sich  also  eine  Datei  ibdata1  in/var/lib/mysql. Diese Datei  ist zunächst 10M groß und wächst dann in Schritten von8MB (weil innodb_autoextend_increment = 8 per Default auf 8 steht).

Diese  Defaults  sind  für  den  effizienten  Betrieb  jedoch  nicht  sehr  gut  gewählt.Zunächst  einmal  sollte  man  innodb_file_per_table  =  1  setzen.  Auf  diese  Weisebekommt  man  pro  Tabelle  ein  .ibd­File.  Dadurch  hat  man  die  Möglichkeit,  denPlatzverbrauch  in  der  Datenbank  Tabellenweise  auch  von  außen  zu  messen  undman gewinnt die Möglichkeit, durch ein "ALTER TABLE t ENGINE=innodb" bzw. ein"OPTIMIZE  TABLE  t"  den  leeren  Platz  in  solchen  Dateien  dem  Betriebssystemwieder zur Disposition zur Stellen.

Wählt  man  innodb_file_per_table  =  1,  dann  sind  die  Defaults  fürinnodb_data_file_path  und  innodb_autoextend_increment  ausreichend,  denn  imibdata1­File wird lediglich das InnoDB­interne Shadow­Datadictionary und das Undo­

Page 5: Die MySQL InnoDB Storage Engine (Teil 2)

Log abgelegt. Auf solchen Installationen erhält man am Ende meist ein ibdata1 in der

Größe von 256M bis 1024M, je nach Maximalbelastung des Undo­Logs.

Muß oder will man InnoDB mit innodb_file_per_table = 0 betreiben, dann werden die

Daten  ebenfalls  im  ibdata1­File  abgelegt. Man  sollte  vorher  sicherstellen,  daß  das

Betriebssystem und auch alle Utilities zur Datensicherung mit sehr großen Dateien

korrekt  umgehen  können.  Ist  das  nicht  der  Fall,  wird  man  ein  sehr  kompliziertes

innodb_data_file_path­Statement  benötigen,  das  ausreichend  viele  ibdata­Files

definiert ­  jedes von ihnen wahrscheinlich so um die 2G groß, oder was  immer das

Limit hier ist.

Angenommen  der  Support  im  Betriebssystem  für  sehr  große  einzelne  Files  ist

ausreichend, dann wird man mit Sicherheit die Schrittweite vergrößern wollen, in der

die  ibdata­Datei  vergrößert  wird  ­  inoodb_autoextend_increment  =  8  sind  als

Schrittweite sicher zu klein. Stattdessen ist es empfehlenswert, sich das Dateisystem

anzusehen, auf dem die Datei angelegt wird, und als Schrittweite etwa 1% bis 5%

der gesamten Dateisystemgröße zu wählen. Auf diese Weise wird das Dateisystem

nach Bedarf in 20 bis 100 Schritten aufgefüllt. Das ist hinreichend klein granular,um

flexibel zu sein, aber das Betriebssystem hat dennoch ausreichend wenige Allocation

Requests  um  die  Datei  weitgehend  unfragmentiert  zu  erzeugen.  Auf  einem

Dateisystem mit 200G Platz wird man also eine Schrittweite von 2048 (2048M = 1%

von 200G) oder gar 10240 (10G = 10240M = 5% von 200G) wählen.

In  jedem  Fall  sollte  ein  Tablespace­File  so  definiert  sein,  daß  es  auf  "autoextend"

konfiguriert  ist,  insbesondere  auch  bei  innodb_file_per_table  =  1.  Wenn  nämlich

durch viele Schreibzugriffe während einer  lang andauernden Transaktion das Undo

Log vorübergehend anschwillt und dabei nicht genug Platz im ibdata­File ist, kommt

es  zu  sehr  seltsamen und  schwer  zu  diagnostizierbaren Fehlermeldungen,  obwohl

auf Dateisystemebene noch genug Platz vorhanden ist.

Außerdem  ist  zu  bedenken,  daß  InnoDB  mehr  Filehandles  verbraucht,  wenn

innodb_file_per_table  =  1  gesetzt  ist  ­  entsprechend  sollte man  innodb_open_files

größer wählen, zum Beispiel ein Filehandle pro Tabelle. Das zieht unter Umständen

auch  eine  Anpassung  von  open_files_limit  nach  sich  ­  hier  müssen  aber  noch

Filehandles für .frm­Dateien und für MyISAM­Tabellen mit dazu gerechnet werden.

Relevante Konfigurationseinträge in der my.cnf (File per Table):

CODE:

# Soll InnoDB mit einer ibd­Datei pro Tabelle betrieben werden

innodb_file_per_table = 1

# Wo soll die ibdata­Datei abgelegt werden (Default: $datadir)# innodb_data_home_dir

# Wie soll die Datei angelegt werden?innodb_data_file_path = "ibdata1:10M:autoextend"

# In was für Schritten (MB) soll die Datei wachsen?innodb_autoextend_increment = 8

# Filehandles hoch drehen#  Ein Filehandle pro InnoDB Tabelleinnodb_open_files = 2048

# Das hier kann man in Linux auch # getrost richtig hoch drehenopen_files_limit  = 32768

Relevante Konfigurationseinträge in der my.cnf (Single­Tablespace):

CODE:

Page 6: Die MySQL InnoDB Storage Engine (Teil 2)

# Soll InnoDB mit einer ibd­Datei pro Tabelle betrieben werden

innodb_file_per_table = 0

# Wo soll die ibdata­Datei abgelegt werden (Default: $datadir)# innodb_data_home_dir

# Wie soll die Datei angelegt werden?#   Tablespace wird hier als 2G große Datei angelegt.innodb_data_file_path = "ibdata1:2048M:autoextend"

# In was für Schritten (MB) soll die Datei wachsen?#   Tablespace wächst hier in 2G Schritten #   (1% einer 200G­Platte)innodb_autoextend_increment = 2048

Wie InnoDB seine Daten auf die Platte malt

Wie wir oben gesehen haben, werden Daten bei der Ausführung von schreibendenKommandos in InnoDB nur gelesen ­ ein INSERT oder UPDATE­Statement erzeugteinen Logbuffer  und als Dirty markierte Pages  im  InnoDB Bufferpool  für  die Datenund das Undo­Log. Bei einem Commit wird der Logbuffer ins Redo­Log geschrieben­  jedenfalls wenn innodb_flush_log_at_trx_commit = 1 gesetzt  ist. MySQL führt denCommit dann als einen Write ins Redo­Log und eine Flush­Operation durch. Letztereleert dann die Betriebssystem­Puffer  in die Platten­Puffer und die Platten­Puffer aufdie Platte.

Selbst  dies  ist  jedoch  eine  relativ  langsame  Operation,  bei  der  Wartezeiten  voneinigen Millisekunden  auf  eine  langsame mechanische Platte  auftreten  ­  jedenfallswenn  man  nicht  eine  spezielle  Platte  für  das  Redo­Log  hat,  die  ausbatteriegepuffertem RAM  besteht.  Daher  besteht  die Möglichkeit,  InnoDB  auf  eineWeise zu betreiben, bei das Warten auf die Platte vom Commit mehr oder wenigerstark entkoppelt wird.

Bei  innodb_flush_log_at_trx_commit  =  2  ist  es  so,  daß  ein Commit  die Daten  ausdem MySQL  in  die Betriebssystem­Puffer  überträgt  ("WRITE"),  aber  ein Schreibender  Betriebssystem­Puffer  auf  die  Platte  ("FLUSH")  nur  einmal  pro  Sekundeerzwingt. Dies  bewirkt,  daß  bei  einem Absturz  des MySQL Serverprozesses  keineDaten verloren gehen können, bei einem Absturz der Server­Hardware jedoch bis zueiner Sekunde Redo­Log fehlen kann. Es existieren also möglicherweise Daten,  fürdie der Anwendung signalisiert wurde, daß sie geschrieben wurden, die aber nichtgeschrieben  worden  sind.  Dafür  ist  diese  Betriebsart  durch  die  WegfallendenWartezeiten auf die langsamen Festplatten sehr viel schneller.

Je  nach  Geschäftsprozeß,  der  hier  implementiert  wird,  kann  es  sein,  daß  dieserFehler  relevant  ist  oder  nicht  ­  aus  der  Sicht  der  Informatik  ist"innodb_flush_log_at_trx_commit = 2" eine Verletzung des ACID­Prinzips nach Coddund daher falsch. Aus der Sicht der Betriebswirtschaft kann das Verhalten dennochkorrekt  sein.  Das  wäre  zum  Beispiel  dann  der  Fall,  wenn  die  verlorenen  Datenreproduzierbar  wären,  oder  wenn  die  Korrektur  der  falschen  Daten  durchKundenservice kostengünstiger wäre als die Hardware, die notwendig wäre, um diebenötigte Performance bei innodb_flush_log_at_trx_commit = 1 zu liefern.

Bei innodb_flush_log_at_trx_commit = 0 wird das Schreibverhalten von InnoDB nochweiter gelockert ­ "Commit" ist nun eine rein logische Operation, die keine Writes undkeine Flushes per initiiert. Stattdessen wird das Redo­Log einmal pro Sekunde durch"WRITE"  an  das  Betriebssystem  übertragen  und  danach  durch  "FLUSH"  einSchreiben der Betriebssystem­Puffer auf die Platte erzwungen. Dies ist jedoch nichtwesentlich schneller als die Einstellung "2".

Page 7: Die MySQL InnoDB Storage Engine (Teil 2)

In  jedem Fall wird  die Datenbank nach einem Crash des MySQL­Serverprozessesoder  der  Hardware  beim  Wiederanlauf  recovern  müssen.  In  jedem  Fall  wird  dieDatenbank  wieder  in  einen  konsistenten  transaktionalen  Zustand  recovern,unabhängig  von  den  Einstellungen  für  innodb_flush_log_at_trx_commit.Unterschiedlich  wird  lediglich  der  Punkt  in  der  Zeit  sein  (die  letzte  geseheneTransaktionsnummer,  zu  der  hin  recovert  wird),  den  die  Datenbank  nach  demWiederanlauf und der Recovery erreicht.

Das  Verhalten  von  InnoDB  läßt  sich  außerdem  noch  mit  Hilfe  derinnodb_flush_method  beeinflussen.  In Unix  sind  die  zugelassenen Werte  für  dieseVariable  "fdatasync"  (der Default),  "O_DSYNC",  "O_DIRECT",  "littlesync",  "nosync",in  Windows  werden  "normal"  und  "unbuffered"  (der  Default)  sowie"async_unbuffered" (der Default in Windows XP und Windows 2000) erkannt.

Die  Idee  bei  O_DSYNC  und  O_DIRECT  ist,  die  Dateien  des  Redo­Log  auf  eineWeise  zu  öffnen,  die  den  Puffermechanismus  des  Betriebssystems  komplettausschaltet  ­ die Datenbank puffert Daten  im  innodb_buffer_pool und  im Redo­Logselbst und es besteht gar keine Notwendigkeit für den File System Buffer Cache desBetriebssystems.  Setzt  man  innodb_flush_method  zum  Beispiel  auf  O_DIRECT  inLinux, wird InnoDB nur noch WRITE­Aufrufe durchführen, aber die Daten nicht mehrmit FLUSH auf die Platte zwingen. Dies  ist auch nicht mehr notwendig, da  ja  jederWRITE bei O_DIRECT ungepuffert direkt auf die Platte geht.

Relevante Konfigurationseinträge in der my.cnf (für Linux):CODE:# Gewünschtes Schreibverhalten für viele Anwendungen

innodb_flush_log_at_trx_commit = 2

innodb_flush_method = O_DIRECT

# Alternativ für ACID­Compliance:

innodb_flush_log_at_trx_commit = 1

innodb_flush_method = O_DIRECT

Concurrency Tickets

InnoDB  funktioniert  besser, wenn  die Anzahl  der Threads  begrenzt  ist,  die  geradeOperationen  innerhalb  der  Storage  Engine  ausführen.  Es  können  sich  gleichzeitiginnodb_thread_concurrency  viele  Threads  in  InnoDB  aufhalten.  Es  existierenverschiedene  Formeln,  mit  denen  man  auf  sinnvolle  Werte  für  diese  Variablekommen  kann  ("Anzahl  der  Cores  mal  zwei",  "Summe  aus  Cores  und  Platten  =Anzahl der Dinge, die wir in Bewegung halten wollen"), aber es ist klar, daß aktuelleVersionen von InnoDB schlechtere Performance zeigen, wenn der Wert zu hoch wird­ derzeit scheint das Limit je nach Load 16 oder 32 zu sein.

Hat  man  mehr  gleichzeitige  Transaktionen  als  innodb_thread_concurrency  zuläßt,müssen überzählige Threads warten. Oft ist es jedoch so, daß ein Thread über dasHandler  Interface  in  die  Storage  Engine  hineingeht,  dort  eine  Operation  wie  KeyLookup durchführt, um dann in die MySQL SQL­Schicht zurück zu kehren. Um eineeinzelne Query zu beantworten sind unter Umständen sehr viele solche Übergängenotwendig.

Damit ein Thread nun nicht  jedesmal warten muß, wenn er  in die  InnoDB StorageEngine  will,  bekommt  er  innodb_concurrency_tickets  viele  "Tickets",  wenn  ihmZugang zur Engine gewährt wird. Er kann also entsprechend viele Wechsel zwischenSQL­Schicht  und  Storage  Engine  machen,  ohen  daß  er  erneut  warten  muß.  Mankann hier mit verschiedenen Werten experimentieren, wenn man eine Maschine mit

Page 8: Die MySQL InnoDB Storage Engine (Teil 2)

sehr vielen CPUs und Festplatten hat und eine sehr hohe Thread Concurrency  fürInnoDB hat. Sinnvolle Werte sind "Anzahl der Records in einem Block", "... in einemSegment" oder "Anzahl der Records, die in dieser Query gelesen werden".

Eine  weitere  Variable  ist  die  innodb_commit_concurrency,  die  die  Anzahl  derThreads  limitiert,  die  gleichzeitig  comitten  können.  Sie  begrenzt  denSpeicherverbrauch im Logbuffer und reguliert Contention auf dem Redo­Log.

Aus historischen Gründen existiert noch eine Variable thread_concurrency. Der Wert,der  hier  übergeben  wird,  endet  im  Code  direkt  in  einem  Aufruf  vonpthread_setconcurrency(),  wird  aber  sonst  nicht  weiter  verwendet.  Diese  Funktionbewirkt  in  den  aktuellen  Implementierungen  von  pthreads  in  Linux  und Solaris  garnicht,  in Versionen von pthreads bis einschließlich Solaris 8 hat  sie  sich  intern aufdas Mapping von Threads zu Kernelthreads ausgewirkt. Für aktuelle Versionen vonBetriebssystemen und MySQL  ist die Variable und der dort eingestellte Werte nichtmehr relevant.

Relevante Konfigurationseinträge in der my.cnf:CODE:innodb_commit_concurrency = 0

innodb_thread_concurrency = 16innodb_concurrency_tickets = 500

Metadatenstrukturen

Wenn  ich  nach  dem  gehe,  was  ich  bei  Kunden  vorfinde,  dann  istinnodb_additional_mem_pool_size eine Variable, die sehr häufig auf seltsame Wertegesetzt wird. Die Variable bestimmt die Größe eines Puffers für Metadatenstrukturen,ist also ein Cache für das interne InnoDB Data Dictionary. Der Default­Wert ist 1 MBund  im normalen Betrieb braucht dieser Puffer niemals größer als 8 MB gesetzt zuwerden.  Ein  Kunde,  der  Tests mit  40.000  InnoDB­Tabellen  vorgenommen  hat,  hathier tatsächlich einmal einen Wert von 20 MB benötigt.

Relevante Konfigurationseinträge in der my.cnf:

CODE:innodb_additional_mem_pool_size = 4M

Gesamtübersicht

Eine  Gesamtübersicht  über  alle  InnoDB­Statusvariablen  undKonfigurationsparameter  findet  man  auf  12.2.4.  InnoDB  Startup  Options  andSystem Variables im Handbuch.Geschrieben von Kristian Köhntopp in MySQL um 11:50 | Kommentare (4) | Trackbacks (5)

TrackbacksTrackback­URL für diesen Eintrag

InnoDB konfigurieren

Eigentlich sollte an dieser Stelle ein (leienhafter) Beitrag von mir zur Konfiguration vonInnoDB (ent)stehen. MySQL­Gott Isotpp ist mir zuvor gekommen. Besser kann manes denke ich nicht erklären. Danke!Weblog: Ich bin root

Page 9: Die MySQL InnoDB Storage Engine (Teil 2)

Aufgenommen: Feb 03, 13:33

InnoDB KonfigurationSehr netter Artikel ueber die Konfiguration der InnoDB Storage Engine von KristianKöhntopp.Weblog: Plog of Christian BerendtAufgenommen: Feb 05, 10:43

InnoDB Konfiguration ­ einfach erklärtKristian Köhntopp hat mal wieder einen Artikel der Sorte "so will ich das erklärtbekommen" geschrieben. Diesmal über "Die InnoDB Storage Engine: Konfiguration"Lesen lohnt sich!Weblog: :: handcode.de ::Aufgenommen: Feb 05, 14:52

InnoDB InternalsChristian Köhntopp hat einen sehr schönen Artikel über die Funktionsweise vonInnoDB sowie der Bedeutung der einzelnen InnoDB spezifischen Optionen in dermy.cnf geschrieben. Vielen Dank! ...Weblog: I, BlogAufgenommen: Feb 06, 17:43

Configuring InnoDB ­ An InnoDB tutorialThis is the english translation of another article in my german language blog. How aretransactions organized physically When InnoDB creates a new transaction it is not yetcommitted. The database has not yet made any promises to the application andWeblog: MySQL­dumpAufgenommen: Feb 07, 08:59

KommentareAnsicht der Kommentare: (Linear | Verschachtelt)

Wow, vielen Dank für diesen tollen Artikel. Genau den hätte ich vor 3 Tagen gesucht. :)#1 Teg am 03.02.2008 13:02

Sieht ja ziemlich so aus, wie wir das haben.

Unsere Hauptanwendung ist ein AAA backend. Wir haben einen Master mit relativwenigen writes (wenige Dutzend pro Minute), auf jedem AAA server ist ein read­onlyslave. Die Datenbank passt gut in den Speicher, demensprechend haben wirinnodb_buffer_pool_size nur ca. 30% größer als die innodb­Files gesetzt. Ist aber m.E.unkritisch, solange man mysqld nicht mit ­­memlock laufen hat.

Interessant finde ich noch innodb_thread_concurrency. Effektiv haben wir ja nur denslave thread, der writes macht, wir möchten aber natürlich möglichst viele gleichzeitigereads. Aktuell haben wir innodb_thread_concurrency=0, also kein Limit, das sollmutex­overhead sparen und tut bis jetzt ohne Probleme. Meinungen dazu? (Falls dasüberhaupt noch jemand liest...)Mysql ist 5.0.51a (debian lenny).#2 Jakob am 07.12.2009 16:07

MySQL 5.1 ist in typischen Benchmarks etwas langsamer als ein MySQL 5.0 ­diese Benchmarks erzeugen aber in der Regel nicht genügend Concurrency. Füruns ist 5.1 auf Nehalem­Maschinen etwa 30% schneller als 5.0, und MySQL 5.4

Page 10: Die MySQL InnoDB Storage Engine (Teil 2)

noch einmal 20% schneller als 5.1 (aber leider nicht GA).

Diese Umstellung bringt wahrscheinlich weitaus mehr als Spielereien an den

Tuning­Parametern von 5.0 betreffend Concurrency.

#2.1 Isotopp (Link) am 07.12.2009 20:19

Lt. MySQL 5.1 Doku ist innodb_open_files unabhängig von open_files_limit. Das liest

sich in diesem Artikel anders. Was ist nun richtig?

Und ­ unabhängig davon, dass beides funktioniert ­ was ist die bevorzugte

Schreibweise von Config­Variablen: Underscore oder Dash?

#3 Laph am 04.02.2011 08:36

Kommentar schreibenName

E­Mail

Homepage

Antwort zu

Kommentar

Umschließende Sterne heben ein Wort hervor (*wort*), per _wort_ kann

ein Wort unterstrichen werden.

Um maschinelle und automatische Übertragung von Spamkommentaren

zu verhindern, bitte die Zeichenfolge im dargestellten Bild in der

Eingabemaske eintragen. Nur wenn die Zeichenfolge richtig eingegeben

wurde, kann der Kommentar angenommen werden. Bitte beachten Sie,

dass Ihr Browser Cookies unterstützen muss, um dieses Verfahren

anzuwenden. 

Hier die Zeichenfolge der Spamschutz­Grafik eintragen: 

BBCode­Formatierung erlaubt  Daten merken?