Blog ·
Die einzige echte Grenze der Rackbelegung
Zwei Techniker wählen gleichzeitig dieselbe Rack-Unit. Beiden meldet das Formular frei. Entscheiden kann nur ein partieller eindeutiger Index, sonst nichts.
Von Provibr
Zwei Techniker platzieren Maschinen im selben Rack. Beide öffnen das Formular, beide schauen auf U neun, beide sehen einen freien Slot, beide drücken auf Speichern. Was Ihr Anwendungscode zwischen diesen beiden Anfragen auch tut, es gibt ein Fenster, in dem beide dieselbe Antwort lesen, und keine noch so gründliche Prüfung vor dem Schreiben schließt es.
Das ist das älteste Wettrennen überhaupt, und es hat genau eine richtige Antwort: Die Datenbank entscheidet. Alles darüber ist dazu da, eine lesbare Ablehnung zu erzeugen, und nicht dazu, eine Kollision zu verhindern. Diese Reihenfolge zu vertauschen ist genau der Weg zu einer Eindeutigkeitsregel, die an einem hektischen Tag leckt, und in einem Rechenzentrum bedeutet ein Leck jemanden mit einem Rollwagen vor einem Rack, das schon voll ist.
Die Grenze ist ein Index
Die Belegung wird absichtlich zweimal gespeichert. Eine Buchung hat eine Kopfzeile, und das ist das, was jemand angelegt hat: diese Seite, von dieser Unit bis zu jener, und bei einer Platzierung die Maschine, die darin steht. Und sie hat eine Zeile je belegtem Slot: dieses Rack, diese Seite, dieses eine U.
Die Slot-Tabelle gibt es aus genau einem Grund. Sie trägt einen partiellen eindeutigen Index auf Rack, Seite und Slot-Nummer, begrenzt auf Zeilen, die nicht freigegeben sind. Dieser Index ist die einzige echte Grenze der Belegung im ganzen System. Nichts anderes kann es sein, denn ein eindeutiger Index kann nicht verknüpfen: Er sieht nur die Spalten der Zeile, auf der er liegt, das Rack und die Seite müssen also auf die Slot-Zeile denormalisiert werden, damit es das Constraint überhaupt geben kann.
Der Preis ist, dass die Freigabe einer Buchung zwei Aktualisierungen innerhalb einer Transaktion sind, denn der Freigabezeitpunkt liegt sowohl auf der Kopfzeile als auch auf den Slots. Der Gegenwert ist, dass die Invariante von der Datenbank durchgesetzt wird und nicht von der Sorgfalt dessen, der die nächste Funktion schreibt.
Wir haben das gemessen, statt darüber nachzudenken. Zwei echte Postgres-Verbindungen, eine gemeinsame Barriere, damit beide in ihrer Transaktion sind, bevor eine von beiden festschreibt, beide beanspruchen vorne U neun. Ergebnis: genau eine geschriebene Buchung, ein Fehler 23505, der diesen Index benennt, und keine verwaiste Kopfzeile, die das Zurückrollen hinterlassen hätte. Das ist der Satz, den man über eine Nebenläufigkeitsgarantie schreiben können möchte, und aus dem Lesen des Codes kann man ihn nicht schreiben.
Wofür die Prüfung vor dem Schreiben wirklich da ist
Es gibt eine reine Funktion, die eine Buchung plant, und sie lehnt auf drei Arten ab, in dieser Reihenfolge.
Die Seite gibt es nicht. Ein offenes Gestell ohne Rückseite ist kein Rack, in dessen Rückseite man etwas hängt, und genau deshalb ist es eine Eigenschaft des Racks und keine Annahme, ob es eine Vorderseite und eine Rückseite unterstützt.
Außerhalb der Grenzen. Der ganze Bereich muss zwischen die Start-Unit des Racks und sein Ende passen, jeweils einschließlich. Racks fangen nicht alle bei eins an und zählen nicht alle aufwärts, das ist also Arithmetik gegen die Geometrie genau dieses Racks und nicht gegen die Zahl zweiundvierzig.
Belegt, und diese Ablehnung trägt die Liste der Slots, die kollidieren. Eine Meldung, die „voll“ sagt, schickt jemanden zurück ins Formular, ohne dass er weiß, wo er suchen soll. Eine Meldung, die sagt, dass vorne U neun und U zehn belegt sind, schickt ihn zur Antwort.
Nichts davon ist die Grenze. Beide Techniker aus dem ersten Absatz kommen an allen dreien vorbei. Die Funktion gibt es, damit der gewöhnliche Fall, nämlich einer nach dem anderen, der sich irrt, einen Satz erzeugt statt eines Datenbankfehlercodes.
Unbekannte Tiefe verhält sich wie volle Tiefe
Jede Maschine hat eine Tiefenklasse: voll, halb oder unbekannt. Ein Gerät halber Tiefe beansprucht nur die Seite, an der es hängt. Ein Gerät voller Tiefe beansprucht Vorderseite und Rückseite.
Unbekannt beansprucht ebenfalls Vorderseite und Rückseite, und diese Wahl ist es wert, verteidigt zu werden, denn die intuitive Voreinstellung ist die umgekehrte. Unbekannt fühlt sich an wie fehlende Daten, die man später nachträgt, und während man wartet, scheint es harmlos, die andere Seite frei zu lassen.
Harmlos ist es nicht. Eine Maschine, deren Tiefe sich als voll herausstellt, lässt sich nicht einbauen, wenn inzwischen jemand die Rückseite gefüllt hat, und die Korrektur passiert, wenn die Maschine schon vor Ort ist. Die Rückseite zu sperren kostet Sie einen Slot, den Sie vielleicht gehabt hätten. Sie nicht zu sperren kostet Sie eine Lieferung. Unbekannt ist nicht die Abwesenheit eines Constraints, es ist ein Constraint, das Sie noch nicht benennen können, und die sichere Seite davon ist die vorsichtige.
Dasselbe Prinzip zieht sich durch den Rest des Kapazitätsmodells: ein unbekanntes Gewicht, eine unbekannte Leistungsaufnahme oder ein veralteter Buchungszustand lesen sich als unbekannt oder gesperrt und nie als freie Kapazität.
Eine Platzierung verfällt nie
Buchungen gibt es in vier Arten. Eine Platzierung ist eine Maschine, die physisch da ist. Eine Sperrung ist Platz, der für die Verkabelung aus dem Betrieb genommen wird. Eine Umzugssperre und eine Reservierung sind die beiden, die Platz für etwas freihalten, das unterwegs oder bestellt ist. Nur die erste hat heute einen Bildschirm; die anderen drei gibt es als Daten, damit das Grundelement eine Sache ist statt vier ähnlicher Dinge.
Ein Check-Constraint in der Datenbank setzt durch, dass eine Platzierung keinen Verfall hat. Das klingt nach einer kleinen Regel. Was sie verhindert, ist eine Zeile, die an einem Dienstag still aufhört mitzuzählen, während die Maschine noch festgeschraubt ist, also ein Rack, in dem die Software einen freien Slot vermutet. Eine verfallende Reservierung ist eine Funktion; eine verfallende Platzierung ist eine Lüge mit einem Zeitschalter daran.
Ein zweiter Check verlangt, dass eine Platzierung eine Maschine hat, denn die anderen drei Arten haben berechtigterweise keine, und ein partieller eindeutiger Index erlaubt höchstens eine aktive Platzierung je Maschine. Ohne diesen Index kann dieselbe Maschine gleichzeitig in zwei Racks erfasst sein. Das ist kein Datenqualitätsproblem, das Ihnen in einem Bericht auffällt; es ist ein Problem, das Ihnen auffällt, wenn jemand am falschen Rack steht.
Wissenswert zu Indizes dieser Form: Sie gelten global und nicht je Organisation. Eine Maschine, die bereits eine aktive Zeile trägt, kollidiert mit dem eindeutigen Constraint und nicht mit einer Rechteprüfung, auch dann, wenn der zweite Versuch aus einer anderen Organisation kommt. Das ist die sichere Seite, und es bedeutet auch, dass der Test für den Fall mit zwei Organisationen eine dritte Maschine braucht, denn das Constraint greift, bevor die Eigentumslogik überhaupt läuft.
Dieselbe Form eine Ebene höher
Eine Maschine an einen Kunden zu übergeben hat dieselbe Struktur, und dafür braucht es zwei Indizes statt eines, denn es sind zwei Invarianten, die Menschen gewohnheitsmäßig als einen Satz aussprechen.
Ein Dienst liegt auf höchstens einer Maschine. Ohne das kann ein Dienst auf zwei Maschinen zeigen, und seine Standortkarte zeigt in zwei Richtungen.
Eine Maschine ist an höchstens einen Dienst ausgegeben. Ohne das wird dieselbe Maschine zweimal verkauft, und Sie erfahren es, wenn zwei Kunden anrufen.
Beide sind partielle eindeutige Indizes auf Zeilen, deren Enddatum noch leer ist, was dieselbe Konstruktion ist wie beim Slot-Index und aus demselben Grund: Die Prüfung in der Anwendung erzeugt die lesbare Ablehnung, der Index entscheidet, wer gewinnt.
Eine Regel ließ sich nicht in die Datenbank bringen. Eine Bindung muss auf einen Dedicated-Dienst zeigen, und ein Check-Constraint kann keine andere Tabelle lesen. Diese eine lebt in der Funktion, die die Bindung schreibt, und es lohnt sich, ausdrücklich zu sagen, welche Ihrer Regeln vom Schema und welche von einem Codepfad durchgesetzt werden, denn die zweite Art ist nur so gut wie die Zahl der Schreibwege, die Sie daran denken, durch sie zu leiten.
Bindungen sind historisch und nicht aktuell. Das Enddatum ist das, was die Zeile inaktiv macht, und jedes Lesen eines physischen Standorts filtert darauf und auf die Organisation sowohl der Bindung als auch der Maschine. Lassen Sie diese Filter weg, und ein früherer Kunde liest Rack und Unit des Kunden, der nach ihm kam. Das ist rot bewiesen worden, bevor es behoben wurde, und das ist die einzige Art zu wissen, dass ein Filter arbeitet.
Was wir aufschreiben würden
- Legen Sie die Eindeutigkeit dorthin, wo die Zeile ist. Braucht das Constraint eine Verknüpfung, denormalisieren Sie die Spalten, die es braucht; ein Index kann nicht verknüpfen, und ein Trigger ist kein Constraint.
- Materialisieren Sie die Einheit, um die gestritten wird. Eine Zeile je belegtem Slot, kein Bereich auf einer Kopfzeile, denn ein Bereich kann gegen einen anderen Bereich nicht eindeutig sein.
- Beweisen Sie das Wettrennen mit zwei Verbindungen und einer Barriere. Über Isolationsstufen nachzudenken ist kein Beleg.
- Lassen Sie die Vorprüfung eine Meldung sein und keine Abwehr, und lassen Sie sie die genauen Slots benennen, die kollidieren.
- Lassen Sie unbekannt sich wie der teure Fall verhalten, damit eine fehlende Messung nie als freier Platz erscheint.
Zur Klarheit darüber, wo das steht: Die Arbeit an der Rechenzentrumslogistik liegt hinter einem Rollout-Schalter, der standardmäßig aus ist, mit einer Einstellung je Organisation darüber, nichts davon ist also heute käuflich. Zwei Dinge sind unbewiesen: Die Messung der Nebenläufigkeit lief in einem direkten Datenbanktest gegen Sperrungen und nicht gegen den Weg der Platzierung selbst, und für die Arten Umzugssperre und Reservierung gibt es noch keinen Schreiber. Die weitere Gewohnheit, die Datenbank entscheiden zu lassen, taucht in diesem Produkt auch anderswo auf, in wie Adressen aus einem Pool vergeben werden und in wie ein vmid-Bereich in Wahrheit eine Rechtegrenze ist.
Aus der Rechenzentrumsarbeit bei Provibr. Warum die fünf Kapazitätsfragen über einem Rack nicht addiert werden dürfen, steht in Rackplatz ist keine Kapazität, und was geschieht, wenn ein externes System zu wissen behauptet, wo eine Maschine steht, findet sich in Wenn NetBox die Quelle der Wahrheit ist.