Erlebnis Lauf deutsche Weinstraße

Da hatte ich mir doch selbst ein tolles Geburtstagsgeschenk gemacht – am Geburtstag noch ordentlich futtern ohne Reue, denn am nächsten Tag war ich für den Weinstraßen-Marathon gemeldet.
In der Hand hatte ich den Flyer schon einige Mal auf diversen Laufveranstaltungen – den Ausschlag gab dann Anfang des Jahres meine Lauf-Kollegin Helga aus Nürnberg – sie hatte sich angemeldet um mal in den Raum Mannheim und Umgebung zu kommen. Da konnte ich dann natürlich nicht zurück stecken. Da machte es auch nichts, dass bereits in vier Wochen der Heimat-Marathon in Mannheim stattfindet. Das sollte zur Regeneration reichen.
Helga konnte nun leider verletzungsbedingt nicht teilnehmen – meine Anmeldung hatte ich aber und also gab es auch keinen Grund zu kneifen.

So reihe ich mich am Sonntag um kurz vor zehn in die Startaufstellung am Haus der deutschen Weinstraße in Bockenheim bei Grünstadt ein. Auf der Anfahrt mit dem Shuttlebus vom Parkplatz im Gewerbegebiet an der Autobahn bekommt man einen ersten Eindruck der Strecke – sie läuft teilweise auf der Bundesstraße. Auch warnen mich einige Leute, dass es die Steigungen so verdammt in sich hätten bei dem Lauf, und dass es ab ca. der Hälfte gefühlt nur noch aufwärts geht. Naja das Höhenprofil hatte ich mir ungefähr angeschaut, aber nicht im Detail. Sollte man sich echt angewöhnen. Aber was solls, ich bin auch Ulm ohne große Kenntnis des Profils gelaufen da werden doch die 42km hier auch nicht das Drama werden.

Pünktlich um 10:00h gehts los – zumindest direkt an der Startlinie – bis sich der Pulk endlich in Bewegung setzt dauert es denn doch etwas länger. Ich habe mich bei irgendwo um die 4:00h Zielzeit eingeordnet – alles was drunter ist, ist ok und wenns nicht hinhaut ist das auch kein Drama.
Etwas Sorge bereitet mir noch das Wetter – es ist recht windig und kühl, und die Regenwolken sehen auch nicht gerade vertrauenerweckend aus. Dazu die Berichte von Teilnehmern der Vorgänger-Veranstaltungen: Regen, Hagel, alles schon dagewesen bei diesem Lauf. Kurzzeitig fühle ich mich an die Beschreibung des Amberger Ultra Laufs erinnert…

Aber Schluss mit der Denkerei – die Startlinie ist überquert, jetzt heißt es Laufen. Es geht mit der Masse durch die enge Hauptstraße von Bockenheim und am Ende von Bockenheim die erste nennenswerte Steigung hoch – kurz vor der Kuppe steht auch schon das Schild für Kilometer 2 – noch 40 km – da fühlt man sich doch gleich besser … ich projeziere es innerlich auf die Strecke in Ulm – dort fangen die wahren Freuden erst nach diesem Kilometer so richtig an…

Nun geht es aber erst mal wieder bergab – und nicht so knapp – die Schilder in der Gegenrichtung mahnen: Da musst du nachher auch wieder hoch! Aber so lange es läuft lasse ich es laufen … kurz nach Kilometer drei geht es dann auch wieder bergan durch Asselheim, vorbei an der ersten Versorgungsstelle – aber noch brauche ich nichts. Stattdessen zieht es mich weiter nach Grünstadt – nach der Steigung geht es dort ganz sachte immer bergab – gut zu Laufen, und an der Strecke ist auch reichlich was los. Es geht mitten durch die Fußgänger-Zone. Gelegentlich mal wieder ein wenig aufwärts aber alles nicht der Rede wert. Kurz nach der Autobahnunterquerung suche ich dann doch mal das Dixi-Haus auf – ich hatte es mit der Menge Wasser vor dem Start mal wieder übertrieben. Nach dem Besuch des Tempels der Erleichterung läuft es sich auch gleich etwas entspannter.

Es geht wieder mal hoch – kein Wunder wir laufen ja auch durch die Weinberge. Dieser Begriff wird einem beim Laufen erst so richtig bewusst – in seiner ganzen Schönheit. Langsam aber sicher nähern wir uns der Streckenweiche bei 8,6km – noch fühle ich mich sehr gut ungefähr ein Fünftel der Strecke ist geschafft. Kurz vor der Verzweigung geht es nochmal ein kurzes Stück mit 16% Gefälle hinunter. Gut das wir diesen Teil der Strecke nicht auch wieder hoch müssen. Nach der Abspaltung des Halbmarathons wird es ruhiger – es sind weniger Läufer auf dieser Strecke unterwegs und ich bin froh, dass die Abzweigung so früh kam – jetzt kann ich mich nicht mehr umentscheiden – das spornt mich dann doch etwas an.
In Kleinkarlbach gibt es wieder eine Versorgungsstation, ich greife mir ein Stück Banane und weiter geht es. Das nächste Schild kommt mir komisch vor – als hätte ich gerade 2 Kilometer im Flug überwunden und in einer absoluten Spitzenzeit … bis ich erkenne: Das ist das Schild der Halbmarathon-Strecke, die hier nochmal kurz gemeinsam verläuft (ein Wechsel ist hier logischerweise nicht mehr möglich). Am Ortsausgang geht es scharf rechts: Als erstes nehme ich das Schild für Kilometer 10 wahr (das passt jetzt auch schon eher). Dann sehe ich die Steigung und weiß schlagartig warum der nächste Ort: Bobenheim am Berg heißt. Gut das es nicht heißt auf dem Berg … auch wenn es mir so vorkommt. Die Steigung komme ich aber dennoch recht gut hoch, auch mit dem Hintergedanken: Wenn du oben bist, hast du das Viertel sicher hinter dir. Etwas ärgerlich ist in dem Zusammenhang der weiterhin kalte Wind und die unfreiwillige Dusche von oben – aber es gibt nur eine Richtung: Weiter nach vorn!

Nach Bobenheim geht es weiter zum nächsten entsprechend markierten Ort: Weisenheim am Berg – und es geht immer noch bergan – wenn auch recht flach, aber es macht sich doch langsam bemerkbar. Durch Weisenheim selbst geht es dann wieder etwas bergab – aber auch nur bis zum Ortsausgang – dort geht es dann besagten Berg hoch. Noch kann ich gut laufen, die Zeiten pro Kilometer varieren zwar stark mit dem Höhenprofil, aber irgendwas um die 5 bis 5:45 kommt immer noch raus – damit bin ich doch recht zufrieden. Mit angehmene Gefälle geht es nach Leistadt einen Vorort von Bad-Dürkheim, und auch danach geht es kontinuierlich bergab. Entlang der Bundesstraße geht es über fast 3 Kilometer nur bergab – eine Belastung der besonderen Art. Ich verfluche es etwas, dass ich an der letzten Verpflegungsstelle nicht mehr zugegriffen habe – die drei Kilometer würden sich hervorragend eigenen um etwas Nahrung zu sich zu nehmen und Energiedepots aufzufüllen. Die Zeiten gefallen mir: 4:20 lese ich für einen Kilometer ab – deutlich zu schnell – ich drossle also trotz Schwerkraftantrieb das Tempo etwas.

In ettlichen Kurven geht es durch Bad-Dürkheim – endlich wieder flach und dann auch gleich eine Anhöhe zur Innenstadt hoch. Alles ziemlich eng – ich greife mir eine Flasche Iso-Getränk ab und kippe es in mich rein. Der Rest landet zielsicher in der Flasche am Gürtel. Es geht nun einen große Schleife eigentlich immer eben durch die Landschaft – vorbei am Gradierwerk des Kurparks mit herrlicher Salzluft. Zum tief durchatmen bleibt aber wenig Zeit. Es geht in die Felder entlag der Umgehungstraße – ein Schleife die wohl sein muss, damit man auf die notwendige Kilometerzahl kommt – so richtig ansprechend finde ich die Strecke an dieser Stelle aber nicht. Schon interessanter ist die zwischenzeitlich Versorgungstation – immerhin mehr als die Hälfte habe ich ja schon geschafft – soll jetzt noch der große Hammer kommen von wegen nur noch bergauf … ich werde mich überraschen lassen.

Kurz vor Kilometer 25 ist es dann soweit – es geht wieder etwas aufwärts in Richtung Ungstein. Aber noch ist das alles machbar, auch wenn die Muskulatur nach Entlastung schreit. Richtig heftig wird es nach Ungstein – es geht steil bergan nach Kallstadt – ich stelle um auf Ulmer-Gemsengang – also Steigungen hochgehen. Von den Muskeln her habe ich kein Problem – allein es fehlt irgendwie der Treibstoff, die Energie. Und es will wohl nicht mehr besser werden – nix zu merken von einen Runners-High oder dergleichen. Merke: Doch mehr futtern während dem Laufen und doch mal Gel oder was in der Art einpacken. Die Strecke zieht sich weiter nach Herxheim am Berg – ich gehe die meisten Steigungen hoch, auch wenn ich damit irgendwie ein Einzelgänger bleibe – die anderen haben wohl noch mehr Kraft oder haben es sich besser eingeteilt. Immerhin geht es danach mal wieder sachte bergab und ich jogge wieder, wenn auch langsam. Die Zeiten liegen jenseits von Gut und Böse – 7 Minuten teilweise für einen Kilometer – so habe ich mir das nicht vorgestellt.

Kurz vor Dackenheim: Kilometer 30 ist erreicht. Jetz sind es nur noch 12 km und das ist doch eine Strecke die langsam überschaubar wird. Ich motiviere mich und laufe wieder ein Stück, die Steigung in Dackenheim wird wieder gegangen. Die Steigung vor Kirchheim jogge ich zur Hälfte der Rest wird im Gehen zurück gelegt. Gut, dass ich den angebotenen Riesling-Schwamm nich wahrgenommen habe – ich glaube so eine Portion Riesling wäre jetzt ziemlich übel gekommen. Wenn der auch sicherlich energiehaltig gewesen wäre. In Kirchheim steht dann ein erfreuliches Schild: 33km liegen hinter mir – noch 9 km vor mir – also etwas weniger als meine Hausstrecke – ich überlege wo ich wohl dort gerade wäre und motiviere mich auf diese Art und Weise. Es lässt sich auch wieder recht gut joggen, wenn auch nicht so schnell wie gewünscht. Vor Kilometer 34 haben die Streckenplaner noch ein knackige Steigung gepackt – auch hier muss ich wieder gehen. Ab der Kuppe ist die Strecke dann bekannt – es geht auf der gleichen Trasse zurück wie wir gekommen sind.

Alles was es in Grünstadt so schön bergab ging, geht es nun wieder langsam hoch. Die Gehpausen werden wieder kürzer – auch wenn ich sie noch immer brauche. Vorbei an der Getränkestelle in der Fußgängerzone. Dann geht es nochmal wieder etwas bergab nach Asselheim. Auch durch Asselheim ist alles bergab – an der Versorgungstation dort lasse ich mir nochmal Apfelsaftschorle in meine Trinkflasche füllen. Cola oder sonstige Zuckersuppe wäre mir zwar lieber gewesen aber so muss es der Apfelsaft halt tun. Und schon stehe ich vor der berühmten Asselheimer Wand – die letzte beachtenswerte Steigung vor dem Ziel – hier ist nochmal für einen Kilometer gehen angesagt.

Während ich die Steigung hochkraxle frage ich mich langsam ernsthaft wo meine Familie abgelieben ist, die wollten doch irgendwo auf den letzten fünf Kilometern stehen … aber auch egal – es sind ja noch knappe 3 Kilometer – an Aufgeben will ich jetzt gar nicht mehr denken, auch wenn die Wadenmuskulatur teilweise anfängt zu krampfen – aber ich lasse sie einfach nicht. Endlich hat die Steigung ein Ende – noch zwei Kilometer bis ins Ziel – ich beiße die Zähne zusammen und zwinge mich dann doch noch zu joggen – es geht ja auch nochmal bergab.

Der Ortseingang von Bockenheim kommt in Sichtweite – und mit ihm das Kilometerschild 41 – nur noch einer, auch wenn es durch den Ort nochmal etwas hochgeht, aber das muss jetzt irgendwie auch noch klappen, Wind und Wetter zum Trotz, denn der Wind pfeift recht übel durch die Haupstraße und natürlich direkt von vorne… Kurz vor dem Schild für Kilometer 42 steht auch endlich meine Familie und feuert mich tatkräftig an. Noch etwas mehr als 400m liegen vor mir. Kurz nach dem Schild steht auf der linken Seite der Zeitmesswagen mit laufender Uhr auf dem Dach. Sie zeigt 3:58:37 als ich an ihr vorbei komme. Das heizt mich nochmal richtig an – eine 4 will ich vorne nicht stehen sehen. Also ranhalten auf die letzten hundert Meter. Und Tatsache es reicht noch: 3:59:38 brutto – unter 4h – Ziel erreicht!

Reichlich fertig gehe ich in Richtung Versorgunspunkt – zwichendrin gibt es noch die Medallie um den Hals. Nach kurzer Pause kommt dann auch der Fan-Tross ins Ziel – ich organisiere mir derweil erst mal 3 alkoholfreie Weizen und ne Portion Apfelsaft. Nach etwas Pause geht es dann zum Versorgungsbereich – auf dem Weg kann ich noch Gunther Mair, einem meiner Kollegen gratulieren – gerade durchs Ziel gekommen. Ich habe allerdings jetzt andere Ziele: Massage und Dusche heißen die. Die Massage nach dem Lauf ist doch echt eine klasse Erfindung – ich kann mich richtig dabei entspannen. Hinterher geht es noch an der Ausgabe für die privaten Sachen und dann nix wie unter die warme Dusche. Meine Schwester wartet so lange, die Eltern wandern zurück zu ihrem Auto – knapp 4km (also Kurzstrecke ;-)). Meine Schwester begleitet mich zu meinem Auto, denn so richtig fahrtauglich fühle ich mich noch nicht wieder.

Die Fahrt mit dem Shuttlebus ist ob der gesperrten Strecke doch etwas abenteuerlich – einmal quer durch die Pampa bis man endlich wieder am Baumarkt-Parkplatz ankommt. Mit dem eigenen Auto geht es dann weiter in Richtung Bad Dürkheim – ich muss noch die Feier für meinen Geburtstag nachholen, da meine Eltern am Vorabend noch andere Verpflichtungen hatten. Im Nachhinein muss ich sagen: Verdammt wellig dieses Streckenprofil – meine Schwester staunt auch nicht schlecht was ich da hoch und runter bin.
Das Essen darf diesmal richtig kalorien haltig sein – es gibt ein Pfälzer Trio (oder auch als Pfälzer Teller bekannt): Leberknödel, Saumagen, Bratwurst und Sauerkraut dazu. Zum Dessert einen flambierten süßen Flammkuchen mit Apfel-Zimt-Belag (lecker!).

Mittlerweile ist der Muskelkater schon wieder so gut wie weg. Ich bin am Überlegen ob ich mir den Lauf in zwei Jahren nicht doch nochmal antue – wenn man das Profil schon kennt, kann man sich besser drauf einstellen. Man wird sehen. Jetzt ist der Blick erst mal auf den kommenden MLP-Marathon in vier Wochen gerichtet. Ich hoffe Helga hat in zwei Jahren auch die Möglichkeit an diesem schönen Erlebnis-Lauf teilzunehmen.

MySQL InnoDB und das Ende der Welt

Wer erinnert sich noch an den Hype um das Jahr 2000-Problem – sicherlich einige. Mittlerweile schreiben wir das Jahr 2012 und alles scheint in bester Ordnung. Scheint – die Realität sieht manchmal leider etwas anders aus.

Alles beginnt mit ganz harmlosen Sympthomen: Ein Mitarbeiter meldet sich bei mir, er könne in der von mir betreuten Datenbank keine weiteren Datensätze anlegen. Die Fehlermeldung besagt, dass eine Schlüsselverletzung vorliegt.

Erster Ansatz: Nachschauen wo man mal wieder etwas zu restriktiv im Datenmodell oder irgendwo etwas zu simpel im Code gearbeitet hat. Aber leider: Fehlanzeige – nichts offensichtliches zu entdecken.

Nächster Versuch: Man füge einen Datensatz direkt auf SQL-Ebene ein – wichtig dabei, man halte sich so weit wie möglich an das Original beim Einfügen. Also lässt man ganz bewusst das Feld für den Primär-Schlüssel leer – steht ja auf auto_increment und damit meint man macht MySQL doch in der Regel keine Zicken.

Aber: Holla! Was ist denn das? MySQL weigert sich den Datensatz einzufügen, angeblich wegen einer Verletzung des Primär-Schlüssels!

Ein wenig Recherche später findet man dann denn auch die Ursache: Der Zahlenbereich des verwendeten Zahlentyps war am Ende. Nun dachte ich eigentlich, dass MySQL dann hergehen würde und sich irgendwie die nächstbeste freie Zahl nimmt – von mir aus ja auch negativ – ist ja kein Drama. Platz war definitiv noch – denn auch wenn in der Tabelle rund 150.000 Datensätze gespeichert waren, so ist das noch immer deutlich kleiner als die 2147483647 möglichen positiven IDs die ein 32 Bit signed Integer in MySQL zur Verfügung stellt (doppelt so viele nochmal wenn man die negativen Zahlen mitberücksichtigt).

Hotfix in dieser Situation war eigentlich recht einfach: von allen vorhandenen IDs eine möglichst große Zahl abziehen, unter Berücksichtigung der Einschränkung, dass keine Id auf den Spezialwert 0 fallen darf. Einfacher gesagt denn getan – die Tabelle repräsentiert nämlich eigentlich eine Baumstruktur mit einem Verweis auf den Vater der jeweiligen Zeile. Da kommt MySQL mit dem Update leider nicht klar, denn aufgrund der fehlenden Bedingung schnappt sich MySQL einfach einen Lock auf die gesamte Tabelle … und sperrt sich damit für ein on Update Cascade selbst aus 😐
Also doch die etwas härtere Tour:

  1. interne Schlüsselbeschränkung aufheben
  2. Immer gleichzeitig die ID und den Vater-Verweis um die gefundene Zahl dekrementieren (da von allen Werten ein konstanter Wert abgezogen wird entstehen wiederum gültige und konsistente Datensätze
  3. Vaterbeziehung wieder mit einem Schlüssel versehen

Warum so umständlich? – Auto-Increment-Rücksetzen funktioniert mit InnoDB als Engine nicht, siehe auch weiter unten. Fremdschlüssel generell abschalten wäre auch keine Maßnahme gewesen, denn die externen Referenzen haben ja ein “on update cascade” – das erspart die langwierige Nacharbeit an x anderen Tabellen in der Datenbank.
Somit kann jetzt wenigstens erst mal wieder gearbeitet werden – die Arbeit für den Entwickler fängt aber jetzt erst richtig an…
Eine andere Alternative wäre die Vergrößerung des Schlüsselbereichs z.B. auf Bigint gewesen oder evtl. auch nur die Verwendung nicht-negativer Zahlen. Leider nicht ganz so einfach möglich, da die Tabelle an verschiedenen Stellen in der Datenbank referenziert wird und natürlich auch die referenzierenden Schlüsselwerte im Datentyp identisch sein müssen. Das wäre auf die Schnelle auch nicht so trivial gewesen.

Zeit für etwas Ursachenforschung – wie man so schön sagt: Lessons learned. Wie Allgemein üblich handelt es sich bei diesem Fehler nicht um eine singuläre Fehlerquelle sondern das Zusammenspiel mehrere Umstände.
Erste Fragestellung: Warum waren die ID-Werte überhaupt so ins Kraut geschossen?
Hierfür gibt es mehrere Gründe – einer ist die historische Wurzel der Datensätze: Diese stammten aus einer Access-Tabelle mit Replikaten. Hierbei setzt Access den Primärschlüssel nicht mehr auf auto_increment (monoton ansteigend wie sich das gehört) sondern auf Random – und da kommen dann recht fix große und auch negative Zahlen bei raus. Die hatte ich natürlich einfach übernommen.
Nächstest Problem: In der Tabelle fanden in letzter Zeit größere Mengen an Transaktionen statt: Die Tabelle wird teilweise aus einer anderen Tabelle gespeist, dabei werden die Datensätze automatisch generiert. Dieses Tool musste aufgrund von Fehlern mehrfach laufen und hatte teilweise dabei auch größere Mengen Einträge produziert – rund 600.000 an der Zahl bevor der Fehler auffiel und beseitigt werden konnte. Somit war man schon bedrohlich nahe ans Limit heran gekommen.
Soweit zur suboptimalen Verwendung der vorhandenen Schlüsselzahl – aber das war ja nicht alleine ausschlaggebend, immerhin könnte man ja erwarten, dass ein ausgewachsenes Datenbank-System sich selbständig um die Behebung des Notstandes: “Keine Schlüssel mehr da” kümmert. Zumindest sollte man das annehmen. Nun kommen auch hier einige kleinere Probleme zusammen, die dann gemeinsam für den großen Ärger sorgen. Als Grundlage verwendet MySQL zwei verschiedene Datenbank-Engines – MyIsam als klassische Tabellenform, leider kann diese nicht mit Fremdschlüsseln umgehen. Daher gibt es InnoDB als neueren Standard. Diese hat zwar nicht die Performance in Sachen Volltext-Suche, kann dafür aber von Hause aus bereits mit Fremdschlüsseln umgehen. In der aktuellen Entwicklung ein unumgängliches Feature, das kaum ein Datenbankentwickler heute noch missen möchte.
Der Berechnungsalgorithmus für die nächste ID in InnoDB ist recht simpel gestrickt: Die nächste zu verwendende ID berechnet sich stets als max(id)+1 – was in MySQL bei Integer-Werten mit 32 Bit zu einem Fehler führt (erst ab Version 5.5) – der dann durch die Ebenen der Datenbank-Engine nach oben wandert und dort schließlich zum bekannten Fehler führt – leider ist der Hinweis duplicate key for primary da nicht sonderlich hilfreich um gleich die Ursache zu erkennen. Dieser Algorithmus wird auch angestoßen, wenn man den Auto-Increment-Zähler manuell versucht zurück zu setzen, oder bei einem Server-Neustart. Simple Lösungen mag ich ja eigentlich, aber so simpel hätte es in dem Fall doch nicht sein müssen.
Interessanterweise ist der Fehlerfall ja sogar in der Dokumentation beschrieben (siehe hier:) – netter Nebeneffekt: Wenn man als Datentyp BigInt (also 64 Bit-Zahlen) verwendet, dann klappt es auch mit dem Wrap-Around am Ende des Zahlenbereichs, es wird dann wieder bei 1 bzw. im negativen Bereich weiter gezählt. Warum habe ich noch nicht ergründen können, ich vermute mal, dass InnoDB intern schon mit 64 Bit arbeitet.

Kommen wir zu den Lehren für weitere Projkete oder auch nur die Neuanlage neuer Tabellen:

  1. An InnoDB führt kein Weg vorbei wenn Fremmdschlüssel im Spiel sind, und Fremdschlüsselmechanismen sind generell begrüßenswert
  2. Beim Import von Alt-Daten wenn es möglich ist, deren ID-Werte verwerfen und neue vergeben (leider nicht immer ohne größeren Aufwand möglich)
  3. Wenn sinnvoll möglich BigInt als Datentyp für die ID-Spalte verwenden, das schafft Luft und es klappt auch mit dem Überlauf richtig
  4. Für den Fall der Fälle Mittel in Bereitschaft haben, um das Problem durch “Renumerierung” lösen zu können (nicht immer hat man die Zahlen in einem bestimmten Bereich liegen so wie in diesem glücklichen Fall).

Weitere Kommentare herzlich willkommen.