Locking ROW EXCLUSIVE

Hallo,

Ich möchte bei einem kokurierenden INSERT 100% sicher gehen,
das im Feld AIC (Typ BIGSERIAL) innerhalb der INSERT Transaktion
kein anderer Prozess die selbe ID bekommen kann und als Endergebnis
die neue ID, zur weiteren vearbeitung an das rufende Programm zurückgelifert wird.

So sieht mein Statement aus:

BEGIN WORK;

LOCK TABLE
webapp.accounts
IN ROW EXCLUSIVE MODE;

INSERT INTO
webapp.accounts(
createdate,
lastchange,
invoice_id,
account_status,
account_history_id,
account_type,
last_admin_id)
VALUES (‘1.1.2008’, ‘1.1.2008’, 1, 1, 1, 1, 1)

RETURNING aic;
COMMIT WORK;

Daher ergeben sich zwei Fragen.

Ist der LOCKING Mode “ROW EXCLUSIVE” wirklich richtig?
ist aus der Doku nicht richtig zu erkennen für mich

Zumindest im PGADMIN3 wird die Query erfolgreich ausgeführt, aber
am Ende Steht “Abfrageergebnis mit 1 Zeilen wurde unterdrückt”.

Das war vor BEGIN WORK; COMMIT WORK; nicht so. Bekomme ich
da eventuell jetzt meine AIC ID nicht zurück, weil ich jetzt LOCKING
verwende?

Etwas verwirrend…

Nicht schlimm. Mach einfach gar nix. SERIAL macht alles andere. Und zwar richtig.

Andreas

Und was passiert wenn während eines neuen Inserts andere Prozesse
auf den Datensatz zugreifen? Schreibzugriffe müssen zumindest für den
aktuellen Datensatz gesperrt werden. Auch muss sichergestellt werden,
daß der Datensatz entweder ganz (komplett) oder gar nicht eingefügt
wird, da alle anderen Relationen auf diesem Wert aufsetzen.

Du solltest dich ernsthaft mit dem Konzept von Transaktionen, deren Sichtbarkeit (Auswirkung auf andere Transaktionen) und der Funktionsweise des SERIAL-Datentyps auseinandersetzen.

Hinweis: die Dokumentation auf der PG-Webseite ist sehr ausführlich. Was du suchst findet sich am ehesten unter BEGIN, Datentypen->SERIAL, SET TRANSACTION.

Danach sollten deine Fragen beantwortet sein und dein Problem sollte sich in Luft aufgelöst haben.

Das habe ich schon Du Scherzkeks. Mit der Doku habe ich mich schon rummgeschlagen. Ich habe doch wohl ganz klar gesagt, daß das für mich nicht eindeutig ist. Hättest auch genauso gut platt sagen können, benutze Google oder such deine Antwort im Kaffeesatz (leute gibts, ist nicht zu fassen).

Deine zwischenmenschlichen Ausdrucksweisen und dein arrogantes Gehabe sind eindeutig deinem schwachen Charakter zuzuordnen. Geh mal zum Psychologen deines Vertrauens, damit Du eine Ahnung davon bekommst wie Du auf andere Menschen, die Dir neu begegnen wirkst (Betonung liegt auf “neue Menschen” in deinem Umfeld). Du bist wirklich eine
unsympathische, dumme Person oder vielleicht auch ein Fachidiot. Kannst es Dir aussuchen.

Hör auf, andere anzupflaumen.


Mit der Doku habe ich mich schon rummgeschlagen. Ich habe doch wohl ganz klar gesagt, daß das für mich nicht eindeutig ist.

Hast du?
Wo hast du das gesagt.

Das einzige, was du in dem Zusammenhang gesagt hast: der Locking Mode war nicht eindeutig für dich. Hättest du genauer hingeschaut, wäre dir aufgefallen, das ich dich eben nicht auf die Dokumentation für Locking Modes verwiesen habe sondern dir einige konkrete Hinweise gegeben habe, wo du statt dessen nachschauen sollst.


Hättest auch genauso gut platt sagen können, benutze Google oder such deine Antwort im Kaffeesatz (leute gibts, ist nicht zu fassen).

Habe ich aber nicht, ich habe dir sogar konkret gesagt, wo du nachlesen solltest. Wenn du das als Kaffeesatz interpretierst, ist das deine eigene Schuld. Ich werde dir die Dokumentation nicht auch noch vorlesen - das kannst du schon selber erledigen. Ich vertraue darauf, das du neben deinem Rumgeheule und deiner schwachen Ausdrucksweise trotzdem schon des Lesens mächtig bist.


Deine zwischenmenschlichen Ausdrucksweisen und dein arrogantes Gehabe sind eindeutig deinem schwachen Charakter zuzuordnen.

Ach weisst du was: geh wieder zurück auf die Spielwiese, von der du weggelaufen bist.

http://www.pg-forum.de/programmierung/2269-heureka-returning-generated_keys.html#post12884

Inserts fügen in aller Regel neue Datensätze ein - auch wenn es technisch etwas anders funktionieren könnte, sehe ich keine Notwendigkeit für einen Row-lock - denn bis zum commit gibt es für andere TX diese Row einfach nicht.

Die Serial / Sequence werden soweit ich das recherchieren konnte von TX nicht erfasst (um Locks zu vermeiden) das ist auch unkritisch - da es i.d.R. völlig Wurst sein sollte wenn mal ne Lücke aufgrund eines Rollbacks in den IDs vorkommt

Inserts werden immer nur als ganzes nach dem Einfügen sichtbar - mit oder ohne explizite TX. Im Grunde ist jede Operation von einem Client aus gesehen eine Transaktion - im normalen Betrieb gibt es also nie “halben Datensätze” … man muss sich schon ziemlich seltene System-Crashs konstruieren, damit sowas auch nur ansatzweise passiert - naja - sag niemals nie :slight_smile:

Nur denke ich, dass man bei solch einem Problem DIESES Problem (System kaputt) auch nicht mehr hat, denn ein halber Datensatz wäre dann schlicht das Problem nicht mehr.

http://www.postgresql.org/docs/8.3/interactive/functions-sequence.html

Important: > To avoid blocking of concurrent transactions that obtain numbers from the same sequence, a nextval operation is never rolled back; that is, once a value has been fetched it is considered used, even if the transaction that did the nextval later aborts. This means that aborted transactions may leave unused “holes” in the sequence of assigned values. setval operations are never rolled back, either.

D.h. also es wird niemals nicht ein anderer Insert die gleiche ID aus der sequence / serial erhalten, es sei denn, eine andere Transaktion würde die Sequence böse auf irgendeinen Wert einstellen - recreaten oder sowas (was wahrscheinlich sowieso nicht geht) - sowas ist aber sehr sehr boese und sowieso nicht erlaubt.

Damit wäre dann auch ads Aussage “das Problem löst sich in Luft auf” genüge getan.

Jetzt lasst uns kuscheln

“Abfrageergebnis mit 1 Zeilen wurde unterdrückt” meint, dass das Abfrage-Ergebnis nach dem ende der Transaktion (COMMIT) nicht mehr zur Verfügung steht.

Wenn du die ID z.B. in einer Fkt. aus darin begonnenen und abgeschlossene TX transportieren willst, musst du sie vor dem COMMIT in irgendeiner Variable zwischenspeichern und dann zurückliefern.

PGAdmin wird darauf nach dem commit einfach nicht mehr zugreifen koennen - weil - wie oben beschrieben - die TX bereits geschlossen ist, wenn die GUI wieder aktiv wird.

Danke Symbiont das Du dir die Mühe gemacht hast :slight_smile:
Ich werde das ganze mal ohne BEGIN WORK / COMMIT WORK
und ohne LOCKING machen, sollte auch funktionieren wenn ich das
was Du geschrieben hast richtig verstanden habe.

Mir ist halt wichtig, daß im laufenden Betrieb, bei konkurierenden
INSERTS in die Tabelle, der client als überlagerndes Programm unbedingt
die ID sauber zurück bekommt und das sich nicht ein anderer
Client aus was für Gründen auch immer die selbe ID holen oder
festlegen kann.

Eine doofe Frage habe ich noch (sorry): Wie weit geht SERIAL?
Ich meine von 0 bis? Jede ID repräsentiert einen User. Ich rechne
in 2 Jahren mit ca. 2 Millionen Usern. Komme ich da irgendwie an
ein Limit?? Wäre fatal wenn ich nach 2 Jahren die ID’s auf eine
andere Spalte mit größeren Wertigkeitsbereich migrieren müsste!
Mein letzte Info ist Int32 und daher Platz für ca. 4 Milliarden Datenätze
(ID’s) Ist das korrekt?

Deine mangelnde Kritikfähigkeit spricht mal wieder für sich.
Sei gefälligst Du nicht immer so unfrendlich und bratzig, ist ja
nicht zum aushalten!

Ja klar, wir wissen Du bist ein ganz großer Pro Linux Guru (Guru kenn ich, hatte ich immer unterm Amiga, war so ein Blackscreen).

Aber wenn euer Durchlaucht es einrichten können und mal ausnahmsweise
von seinem Linux Nerdturm herabsteigen würde, würde ich ich mich über
eine non zynische und non (ihr seid alles Versager und ich bin der Beste)
Antwort freuen. So nun habe ich mir Luft gemacht, Gewitter vorbei!

Also ich erhalte als max_value für eine Sequenz unter Ubuntu 8.04 mit PostgreSQL 8.3 folgenden Wert:

test=# create sequence test_id_seq;
CREATE SEQUENCE
test=# select max_value from test_id_seq;
      max_value
---------------------
 9223372036854775807
(1 Zeile)

test=#

Ok, wusste nicht das man sowas in derart abfragen kann! Super Sache und danke das Du es mir ermittelt hast, werde mal gucken was Windows XP so hergibt oder obs einen Unterschied macht ;d

es gibt glaub ich verschiedene serial typen
was fuer dich passt musst du selbst entscheiden

im grunde legt der typ serial ja ne sequence an … die wohl immer 64 bit erreichen kann …

WICHTIG ist, dass du aufpasst, dass dein Ziel-Feld also z.B. der PK oder ForeignKey die gewünschte Breite (32 bzw. 64) auch aufnehmen kann.
Es wird dir also nichts nützen wenn dein PK vom Typ Integer (32 bit) ist so wird der per default angelegt wenn du den typ serial wählst.
Du solltest bigserial verwenden, wenn du die 64 bit brauchst, denn dann wird als Feldbreite auch 64 bit erzeugt (bigint glaub ich).

Du kannst natürlich - wenn du schon serial verwendet hast - die typen der entsprechenden felder auch nachträglich ändern.


zu dem commit und returning … du kannst durchaus innerhalb der transaktion das resultset des INSERT - RETURNING weiter verwenden - z.B. in einer trigger- funktion - und verwenden … in deinem fall war es nur so, dass der PGAdmin da nichts mehr vorgefunden hat, weil er erst wieder aktiv wird, wenn er dein SQL-script im eingabe-fenster abgearbetiet hat - und am ende stand ja das commit … ende gelände

Ja, habe BigSerial schon verwendet aber dann muss ich mit den math.
BigInt sachen von Java arbeiten und das gefällt mir überhaupt nicht.
Also wenn int32 ausreicht, solls mir recht sein. 4 Milliarden Datensätze
Spielraum sollten für einige Zeit langen ;D

Sach mal, hast Du schon mit den Bigserials von Java gerarbeitet?
Also da funktioniert ja gar nichts mehr wie bei normalen Ints, wirkt
wie ein Fremdkörper muss ich schcon sagen…

nein hab ich nicht - wenn ich aber derartige keys benötigte, dann würde ich mich wohl auf .equals(…) beschränken … i.d.R. muss man bei einem Key doch nicht mehr wissen - also dass er entweder uebereinstimmt, oder eben nicht

Direkt aus Serial Datentyp:

The type names serial and serial4 are equivalent: both create integer columns. The type names bigserial and serial8 work just the same way, except that they create a bigint column. bigserial should be used if you anticipate the use of more than 2^31 identifiers over the lifetime of the table.

Und aus numerische Datentypen (gleiche Seite):

integer: 4 bytes, range: -2147483648 to +2147483647
bigint: 8 bytes, range: -9223372036854775808 to 9223372036854775807

Ach, noch etwas:
symbiont: danke für den dezenten Hinweis auf den anderen Thread mit einem ähnlichen Tonfall.
marc9022: entweder du schreibst in Zukunft vernünftig und in einem angemessenen Tonfall oder du schreibst hier gar nicht mehr. Die Entscheidung überlasse ich dir selbst.

Hallo,

bitte kommt mal wieder runter! Wir sind Erwachsene Menschen - hoffe ich zumindest - und ich werde hier jede weitere “Stänkerei” kommentarlos löschen!

cu tb.

Ist es Dir zu warm geworden in der Sonne oder was soll das?

Andreas

@Xandrian

Sind das auch Stänkerreien?