Ich frage mich, ob jemand eine gute Möglichkeit zum Erstellen einer eindeutigen zufälligen Integer-ID für einen Primärschlüssel für eine Tabelle kannte. Ich benutze MySQL. Der Wert muss ganzzahlig sein.So erstellen Sie eine eindeutige zufällige Integer-ID für den Primärschlüssel für die Tabelle?
Antwort
Wenn Sie Anregungen haben und es implementieren können, verwenden Sie UUIDs. Die UUID()
-Funktion von MySQL gibt einen 36-Zeichen-Wert zurück, der für ID
verwendet werden kann.
Wenn Sie Ganzzahl verwenden möchten, immer noch, ich denke, Sie müssen eine Funktion getRandID()
erstellen, die Sie in der INSERT
Anweisung verwenden werden. Diese Funktion muss eine zufällige + Überprüfung bestehender IDs verwenden, um eine, die zuvor nicht verwendet wurde, zurückzugeben.
Überprüfen Sie RAND()
Funktion für MySQL.
Wie stellen Sie sicher, dass der Zufallswert nicht gleichzeitig von einer anderen Person verwendet wird? Zum Beispiel erhalten Person A und B dieselbe Zufallszahl.Beide prüfen zur selben Zeit ob es existiert, es werden also beide nicht eingefügt. Natürlich scheitert man wegen der Primärschlüsselbeschränkung. Was machst du, um das zu umgehen? Schließtische? Habe es nie benutzt und irgendwie unbehaglich. – MindGame
Das ist die Schönheit von UUID (Universal Unique Identifier). Zitat Wikipedia: "Die Absicht von UUIDs besteht darin, verteilten Systemen zu ermöglichen, Informationen eindeutig ohne wesentliche zentrale Koordination zu identifizieren. Somit kann jeder eine UUID erstellen und sie verwenden, um etwas mit vernünftiger Sicherheit zu identifizieren, dass der Identifizierer niemals versehentlich von irgendjemandem für irgendetwas verwendet wird Andernfalls können mit UUIDs gekennzeichnete Informationen später zu einer einzigen Datenbank zusammengefasst werden, ohne Namenskonflikte auflösen zu müssen. " –
@Tesh Ich würde nur die Funktion im CATCH wiederholen, wenn aufgrund der UNIQUE-Einschränkung eine Ausnahme aufgetreten ist und fortfahren, bis Sie in der Lage sind, eine Zeile mit dieser Random-ID einzufügen. –
Es gibt eine AUTO_INCREMENT
Funktion. Ich würde das benutzen.
Weitere Beispiele siehe here.
AUTO_INCREMENT
wird Ihre beste Wette dafür sein.
Here sind einige Beispiele.
Wenn Sie möchten, können Sie einstellen, wo der Inkrementwert beginnt (standardmäßig ist es 1).
Als Antwort auf:.„Weil ich diesen Wert verwenden möchten, um Base62 zu kodieren und dann, dass in einer URL für eine ID verwenden, wenn ich Autoinkrement, könnte es für den Benutzer offensichtlich sein, wie die URL-ID wird generiert. "
Wenn Sicherheit das Ziel ist, dann hilft die Verwendung von Base62 selbst mit einer "zufällig" generierten Nummer nicht.
Eine bessere Möglichkeit wäre:
- Sie das Rad nicht neu erfinden - verwenden
AUTO_INCREMENT
- dann eine verschlüsselte Hash-Funktion + eine zufällig generierte Zeichenfolge (in der DB für diese bestimmte URL versteckt) die endgültige „eindeutige ID für diese uRL“
Vielen Dank für Ihre Antwort. Okay, ich benutze Auto Inkrement und dann eine kryptografische Hash-Funktion + eine zufällig generierte Zeichenfolge. Aber ich brauche meine URL, um kurz zu sein. Kurz wie Tinyurl es tut. Durch die Verwendung von kryptografischen erhalten ich nicht eine "einzigartige ID für diese URL", die lang ist? – MindGame
Wie Sie die unique_ids erzeugen zu erzeugen, ist eine sinnvolle Frage - aber sie scheinen eine unproduktiv Annahme über wenn Sie Gene zu machen bewerte sie!
Mein Punkt ist, dass Sie diese eindeutigen IDs zum Zeitpunkt der Erstellung Ihrer Zeilen nicht generieren müssen, da sie im Wesentlichen unabhängig von den Daten sind, die eingefügt werden.
Was ich tue, ist die Vorgenerierung eindeutiger IDs für zukünftige Verwendung, so kann ich meine eigene süße Zeit nehmen und absolut garantieren, dass sie einzigartig sind, und es gibt keine Verarbeitung zum Zeitpunkt des Einfügens.
Zum Beispiel habe ich eine Bestellungstabelle mit order_id drin. Diese ID wird im laufenden Betrieb generiert, wenn der Benutzer die Bestellung inkrementell 1,2,3 usw. für immer eingibt. Der Benutzer muss diese interne ID nicht sehen.
Dann habe ich eine andere Tabelle - unique_ids mit (order_id, unique_id).Ich habe eine Routine, die jede Nacht läuft, die diese Tabelle mit genügend unique_id Zeilen vorlädt, um mehr als die Aufträge abzudecken, die in den nächsten 24 Stunden eingefügt werden könnten. (Wenn ich jemals 10000 Bestellungen an einem Tag bekomme, habe ich ein Problem - aber das wäre ein gutes Problem!)
Dieser Ansatz garantiert Eindeutigkeit und nimmt jede Verarbeitungslast weg von der Einfügetransaktion und in den Stapel Routine, wo es den Benutzer nicht beeinträchtigt.
Wie wäre es dieses Ansatzes (PHP
und MySQL
):
Kurz
- generieren zufällige
number
füruser_id (UNIQUE)
- Zeile einfügen mit generierten
number
alsuser_id
- Wenn inse rted row count gleich 0, gehe zu Punkt 1
Sieht schwer aus? Weiter lesen.
Lange:
Tabelle:
users (user_id int UNIQUE)
Code:
<?php
// values stored in configuration
$min = 1;
$max = 1000000;
$numberOfLoops = 0;
do {
$randomNumber = rand($min, $max);
// the very insert
$insertedRows = insert_to_table(
'INSERT INTO foo_table (user_id) VALUES (:number)',
array(
':number' => $randomNumber
));
$numberOfLoops++;
// the magic
if (!isset($reported) && $numberOfLoops/10 > 0.5) {
/**
* We can assume that at least 50% of numbers
* are already in use, so increment values of
* $min and $max in configuration.
*/
report_this_fact();
$reported = true;
} while ($insertedRows < 1);
- Al l-Werte (
$min
,$max
,0.5
) dienen nur der Erläuterung und haben keine statistische Bedeutung. - Die Funktionen
insert_to_table
undreport_this_fact
sind nicht in PHP integriert. Die Nummern sind auch nur zur Verdeutlichung der Erläuterung.
mein Weg, für beide 32-Bit- und 64-Bit-Plattform. Ergebnis ist 64bit
function hexstr2decstr($hexstr){
$bigint = gmp_init($hexstr, 16);
$bigint_string = gmp_strval($bigint);
return $bigint_string;
}
function generate_64bitid(){
return substr(md5(uniqid(rand(), true)), 16, 16);
}
function dbGetUniqueXXXId(){
for($i = 0; $i < 10; $i++){
$decstr = hexstr2decstr(generate_64bitid());
//check duplicate for mysql.tablexxx
if($dup == false){
return $decstr;
}
}
return false;
}
Sie können eine AUTO_INCREMENT
für Ihre Tabelle verwenden, sondern geben den Benutzern die verschlüsselte Version:
ENCRYPTED_ID: SELECT HEX(AES_ENCRYPT(id, 'my-private-key'));
ID: SELECT AES_DECRYPT(UNHEX(encrypted_id), 'my-private-key');
warum nicht nur 'AUTO_INCREMENT' ? – RobertPitt
Da ich diesen Wert zu Encode zu Base62 verwenden und dann für eine ID in einer URL verwenden möchten. Wenn ich automatisch inkrementiere, kann es für den Benutzer offensichtlich sein, wie die URL-ID erzeugt wird. – MindGame
Um Ihr Sicherheitsproblem zu umgehen, könnten Sie AUTO_INCREMENT verwenden und eine zufällig erstellte Nummer als Feld einfügen. Um Ihre Benutzer-ID zu erhalten, nehmen Sie die AUTO-ID + diese Zufallszahl. Führen Sie es durch einen Hash (SHA128 wird gut funktionieren). Selbst wenn die Zufallszahl die gleiche ist (was nicht realistischerweise der Fall ist), wenn Sie sie mit einer anderen Zahl kombinieren, erhalten Sie mit SHA's Ihre Benutzer-ID. – g19fanatic