2009-06-12 5 views
1

Ich entwerfe ein neues System zum Speichern von Kurzmitteilungen [sic].Sollte ich meine AUTO_INCREMENT ID-Spalte auf 2^32 + 1 statt 0 initialisieren?

Ich werde jede Nachricht durch einen eindeutigen Bezeichner in der Datenbank identifizieren und eine AUTO_INCREMENT -Spalte verwenden, um diese Bezeichner zu generieren.

Herkömmliche Weisheit sagt, dass es okay ist, mit 0 zu beginnen und meine Nachrichten von dort zu nummerieren, aber ich bin besorgt über die Langlebigkeit meines Dienstes. Wenn ich eine externe API mache und es zu 2^31 Nachrichten mache, haben einige Leute, die die API benutzen, meine Kennung fälschlicherweise in einer vorzeichenbehafteten 32-Bit-Ganzzahl gespeichert. An diesem Punkt würden sie überlaufen oder abstürzen oder etwas Schreckliches würde passieren. Ich möchte diese Art von Foo-Pocalypse, wenn möglich, vermeiden.

Sollte ich "UPDATE Nachricht SET ID = 2^32 + 1;" bevor ich meinen Dienst starte und alle dazu zwinge, meine Kennungen von Anfang an als signierte 64-Bit-Nummern zu speichern?

+0

Ich kenne die Besonderheiten Ihres Dienstes nicht, aber wenn Sie sich überhaupt mit der Sicherheit befassen, dann sind automatisch inkrementierende IDs oft eine schlechte Wahl, da sie es viel einfacher macht r für einen Hacker, um IDs für Datensätze vorherzusagen oder zu bestimmen, die sie nicht kennen sollten. Dies kann oder kann nicht für Ihren Service gelten, aber es ist etwas zu beachten. –

+0

Was bedeutet [sic]? – Blorgbeard

+0

http://en.wikipedia.org/wiki/Sic – slacy

Antwort

5

Wenn Sie Ihr Ziel erreichen wollten und die Probleme vermeiden wollten, die cletus erwähnte, ist die Lösung, Ihren Startwert auf 2^32 + 1 zu setzen. Es gibt immer noch genug IDs, und es passt nicht in einen 32-Bit-Wert, signiert oder nicht.

Natürlich ist es die einzig richtige Lösung, den Wertebereich zu dokumentieren und Ihren API- oder Datenkunden eine Anleitung zu geben. Jemand wird immer versuchen, lange in ein Zeichen zu stecken und sich fragen, warum es nicht funktioniert (immer)

3

Tatsächlich kann 0 mit vielen Persistenzbibliotheken problematisch sein. Das liegt daran, dass sie es als eine Art Sentinel-Wert verwenden (ein Ersatz für NULL). Zu Recht oder zu Unrecht würde ich vermeiden, 0 als Primärschlüsselwert zu verwenden. Die Konvention soll bei 1 beginnen und nach oben gehen. Bei negativen Zahlen werden Sie die Leute wahrscheinlich ohne guten Grund verwirren.

+0

Wie wäre es mit 1 + 2^32 dann zu starten? Das einzige Problem, das ich dort sehen kann, ist, dass es meinen verfügbaren ID-Bereich um 2^32 Werte reduziert, was wahrscheinlich kein Problem in einem 64-Bit-ID-Raum ist. – slacy

+1

Was Cletus gesagt hat. Machen Sie einfach die Docs und Wsdl (oder was hast du) klar, dass ID ein int64 ist und nennen Sie es einen Tag. –

+0

Das Problem ist, dass Dokumentation möglicherweise nicht genug ist - ich kann nie garantieren, dass jeder API-Benutzer "das Richtige" für diese Zahlen tut, und am Ende bei 2^31-1 brechen kann, wenn sie signed int32 und 2^verwenden 32 + 1, wenn sie unsigned int verwendet. Ich kann nie sagen, was sie tun, da ich ihren Code nicht kontrolliere. Twitpokalypse! – slacy

3

Was wäre, wenn Sie eine Reihe von Test-Suites oder einen Test-Service zur Verfügung gestellt, die Nachrichten in der "High, aber immer noch gültig "Bereich und überzeugen Sie Ihre Service-Nutzer, sie zu verwenden, um ihren Code zu validieren ist richtig? Ausgehend von einem willkürlichen Wert aus defensiven Gründen ist es etwas komisch für mich; Die Bereitstellung von Gesundheitstests reibt mich richtig.

+0

Was ist, wenn ich die größte runde Zahl über 2^32 wähle? Sag, 5000000000? Macht dich das besser? – slacy

+0

Ich mag die Idee einer Regressionssuite. Kann jemand bitte dies den Leuten bei http://apiwiki.twitter.com vorschlagen – slacy

+0

Ein bisschen besser. :) Ich habe einmal eine große nicht-runde Zahl gewählt, um eine öffentlich sichtbare ID zu erstellen, so dass es aussah, als hätten wir mehr Traffic als wir. Dies zu tun, um Leuten zu helfen, die die Dokumentation nicht lesen können - weniger interessiert. ;) – Talljoe

1

Wenn alle lebenden auf dem Planeten eine Nachricht pro Sekunde jede Sekunde non-stop gesendet haben, würde Ihr Zähler nicht bis zum Jahr mit 64-Bit-Ganzzahlen wickeln.

Wahrscheinlich würde nur bei 1 beginnen würde ausreichen.

(Aber wenn Sie an der unteren Grenze beginnen würde, würde es in den Anfang 2092 erweitern)

+0

Deine Mathe ist scheiße, lavinio. ;) vorzeichenbehaftete 32-Bit-Ganzzahlen bei ~ 2 Milliarden, unsigniert bei ~ 4. Es gibt mehr als 7 Milliarden Menschen auf der Erde. Und das hat Twitter schon in dieser Woche erlebt. http://www.twitpocalypse.com/ – richardtallent

+0

Verwendung von 64-Bit-Ganzzahlen mit Vorzeichen: 2^63 ÷ 7000000000 ÷ 365,25 ÷ 24 ÷ 60 ÷ 60 ≈ 41 2009 + 41 = 2050 (Der ursprüngliche Beitrag erwähnte 64-Bit- Ganzzahlen, das ist, was ich mit ging. Meine Mathematik ist nicht schlecht, mein Englisch tut;).) – lavinio

+0

Das Überschreiten von 2^63 ist nicht das Problem, es übersteigt 2^31, also obwohl die 2050-Mathematik richtig ist, sind 2 Milliarden (dh 2^31) nicht mehr so ​​groß, besonders wenn du ' Es gibt Skripte, die Nachrichten erzeugen, keine Maschinen. – slacy

0

Ich will nicht der nächste Twitter sein, nicht wahr? lol

Wenn Sie Bedenken hinsichtlich der Skalierbarkeit haben, sollten Sie stattdessen eine GUID (uniqueidentifier) ​​verwenden.

Sie sind nur 16 Bytes (doppelt so groß wie ein bigint), aber sie können unabhängig voneinander auf mehreren Datenbank- oder BL-Servern zugewiesen werden, ohne sich um Kollisionen kümmern zu müssen.

Da sie zufällig sind, verwenden Sie NEWSEQUENTIALID() (in SQL Server) oder eine COMB-Technik (in Ihrer Geschäftslogik oder Pre-MSSQL 2005-Datenbank), um sicherzustellen, dass jede GUID "höher" ist als die letzte (Geschwindigkeiten fügt ein in deinen Tisch).

Wenn Sie mit einer so hohen Zahl beginnen, werden einige "Genie" -Programmierer entweder 2^32 subtrahieren, um sie in ein int zu drücken, oder ignorieren einfach die erste Ziffer (die "immer gleich" ist) erste Milliarde Nachrichten).

+0

Die Versuchung eines AUTO_INCREMENT-Wertes ist sehr hoch, obwohl ich jetzt denke, dass ich vielleicht nur einen zufälligen 128-Bit-Wert für jeden Eintrag verwende. Ich bin mir nicht wirklich sicher, dass ich etwas so Anspruchsvolles (und Schwergewicht) wie eine GUID brauche. Die Kennungen sind privat für mein System. Das Problem ist, dass ich gerne möchte, dass meine RDBMS-Engine (MySQL) diese Werte automatisch zuweist. – slacy

1

Warum inkrementierende IDs verwenden? Diese erfordern eine Sperrung und werden jegliche Pläne zur Verteilung Ihres Dienstes über mehrere Maschinen zunichte machen. Ich würde UUIDs verwenden. API-Benutzer werden diese wahrscheinlich als undurchsichtige Zeichenketten speichern, was bedeutet, dass Sie das Schema wahrscheinlich später ändern können, wenn Sie möchten.

Wenn Sie wollen sicherstellen, dass Nachrichten einen Auftrag haben, die Bestellung wie eine verkettete Liste implementieren:

--- 
id: 61746144-3A3A-5555-4944-3D5343414C41 
msg: "Hello, world" 
next: 006F6F66-0000-0000-655F-444E53000000 
prev: null 
posted_by: jrockway 
--- 
id: 006F6F66-0000-0000-655F-444E5300000 
msg: "This is my second message EVER!" 
next: 00726162-0000-0000-655F-444E53000000 
prev: 61746144-3A3A-5555-4944-3D5343414C41 
posted_by: jrockway 
--- 
id: 00726162-0000-0000-655F-444E53000000 
msg: "OH HAI" 
next: null 
prev: 006F6F66-0000-0000-655F-444E5300000 
posted_by: jrockway 

(Als beiseite, wenn Sie tatsächlich die Ergebnisse als YAML Rückkehr sind, können Sie & verwenden und * Referenzen statt nur die IDs als Daten zu verwenden.Dann erhält der Client die verknüpfte Listenstruktur "kostenlos".)

1

Eine Sache, die ich nicht verstehe, ist, warum Entwickler nicht begreifen, dass sie nicht müssen ihr AUTO_INCREMENT Feld freilegen. Zum Beispiel wird richardtallent mit Guids als Primärschlüssel erwähnt. Ich sage, mach es besser. Verwenden Sie einen 64-Bit-Int für Ihre Tabellen-ID/den Primärschlüssel, aber verwenden Sie auch eine GUID oder etwas Ähnliches als Ihre öffentlich zugängliche ID.

Ein Beispiel Message Tabelle:

Name   | Data Type 
------------------------------------- 
Id    | BigInt - Primary Key 
Code   | Guid 
Message  | Text 
DateCreated | DateTime 

Dann sieht Ihre Daten wie:

Id | Code         Message DateCreated 
------------------------------------------------------------------------------- 
1 | 81e3ab7e-dde8-4c43-b9eb-4915966cf2c4 | ....... | 2008-09-25T19:07:32-07:00 
2 | c69a5ca7-f984-43dd-8884-c24c7e01720d | ....... | 2007-07-22T18:00:02-07:00 
3 | dc17db92-a62a-4571-b5bf-d1619210245a | ....... | 2001-01-09T06:04:22-08:00 
4 | 700910f9-a191-4f63-9e80-bdc691b0c67f | ....... | 2004-08-06T15:44:04-07:00 
5 | 3b094cf9-f6ab-458e-965d-8bda6afeb54d | ....... | 2005-07-16T18:10:51-07:00 

Wo Code ist, was Sie für die Öffentlichkeit aussetzen würde, ob es sich um eine URL, Dienstleistung, CSV, XML sein usw.

+0

Was ist der Sinn einer ID-Spalte in Ihrem Beispiel? – jrockway

+0

Wird immer noch intern für Fremdschlüssel verwendet und könnte weiterhin in internen Anwendungen verwendet werden. Der springende Punkt ist, dass Sie es nicht öffentlich machen müssen. –

+0

Die Sache, die ich an den GUID-basierten Ideen nicht mag, ist, dass es bedeutet, dass ich diese großen und unheiligen Zahlen in meinen URLs aufdecken würde. d. h. http: // mysite/message/3b094cf9-f6ab-458e-965d-8bdaafeb54d anstelle von http: // mysite/message/5. Ich mag die Letzteren, obwohl, sobald Sie in die Milliarden kommen, es keinen großen Unterschied zwischen den 2 Schemas gibt. – slacy