2016-04-07 16 views
0

So habe ich derzeit eine primäre Postgres-Datenbank, die mehrere Benutzer aus verschiedenen Anwendungen behandelt. Eines der Probleme hinsichtlich der Parallelität ist, dass wenn AppOne und AppTwo Benutzer gleichzeitig hinzufügen möchten.Verwenden Sie PostgreSQL Unique ID für Zeile beim Einfügen

Momentan wird AppOne eine Zufallszahl erzeugen (muss 10 Ziffern lang sein) und dann prüfen, ob der Wert in der Datenbank existiert, wenn er nicht existiert, wird er den Benutzer mit diesem Wert in a einfügen Spalte namens user_url (für ihre URL verwendet).

Jetzt, wie Sie sich vorstellen können, wenn zwischendurch die Zeit für die Generierung, Prüfung oder das Einfügen von AppTwo eine Anfrage zum Hinzufügen eines Benutzers stellt, können wir wiederholt eindeutige Werte haben (es ist passiert). Ich möchte dieses Problem möglicherweise mit Postgres-Triggern lösen.

Ich weiß, dass ich Transaktionen verwenden kann, aber ich möchte nicht die Datenbank halten, ich würde lieber die eindeutige Zahlenfolge durch eine Funktion erstellen und auf der Datenbankseite auslösen, so wie ich es skaliere Ich muss mich nicht um die Bedingungen im Rennen sorgen. Sobald der Auslöser seine Sache macht, kann ich dann den neu hinzugefügten Benutzer mit all seinen Daten einschließlich der eindeutigen ID erhalten.

so ideal

CREATE OR REPLACE FUNCTION set_unique_number(...) RETURNS trigger AS $$ 
DECLARE 
    BEGIN 
    ....something here 
    RETURN new; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER insert_unique_url_id BEFORE INSERT ... PROCEDURE  
set_unique_number(...); 

wäre es eine Funktion sein, die die Nummer und fügt es in die Zeile erzeugt, die durch einen Auslöser von BEFORE INSERT ausgeführt werden würde. Ich kann mich irren.

Jede Hilfe/würden Vorschläge hilfreich

EDIT sein: Ich will es so, dass es keine Sequenz zu den Zahlen. Auf diese Weise konnten die Benutzer die URL des nächsten Benutzers nicht erraten.

Dank

+2

Überprüfen Sie die Verwendung von Sequenzgeneratoren in PostgreSQL. Sie können die Eindeutigkeit ohne den Overhead und die Ungewissheit, in einer lesekonsistenten Umgebung zu validieren, virtuell garantieren. –

Antwort

0

Warum Sie UUID-ossp Erweiterung nicht verwenden? Es erlaubt Ihnen, UUIDs innerhalb von Postgres selbst zu generieren.

Heres a good tutorial wie Sie diese als Primärschlüssel sogar verwenden.

2

9.000.000.000 ist klein genug Nummer, dass Geburtstag Problem wird garantieren, dass Sie beginnen werden, Kollisionen sehr bald zu sehen.

Ich denke, dass Sie dieses Problem umgehen können, während gleichzeitige Einsätze weiterhin unter Verwendung von advisory locking möglich sind. Ihr Verfahren könnte wie folgt aussehen (in Pseudo-Code):

while (true) { 
    start transaction; 
    bigint new_id = floor(random())*9000000000+1000000000; 
    if select pg_try_advisory_xact_lock(new_id) { 
    if select not exists id from url where id=new_id { 
     insert into url (id, ...) values (new_id, ...); 
     commit; 
     break; 
    } 
    } 
    commit; 
} 

Dieses Verfahren wird niemals enden, wenn Sie 9000000000 Zeilen in der Datenbank haben würden. Sie müssen es extern implementieren, da Postgres-Prozeduren mehrere Transaktionen innerhalb einer Prozedur nicht zulassen. Es könnte möglich sein, mit Ausnahmen zu arbeiten, aber es wird ziemlich kompliziert sein.

Verwandte Themen