SQL Locks

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

SQL Locks

Beitrag von Halan »

Ahoi,

heute komme ich mal mit einem SQL-Problem zu euch.

Wie ihr vielleicht mitbekommen habt arbeite ich an einem kleine Online Projekt. Ist aber eigentlich irrelevant weil das Problem eigentlich sehr einfach zu beschreiben ist. Jedes Objekt in meiner Simulation hat eine ID. Und ich arbeite gerade an einem Vergabemechanismus für neue IDs.

In meiner PostgreSQL-Datenbank habe ich eine Tabelle "GlobalValues" mit (wie der Name schon sagt ;) ) globalen Variablen. Dort wird die zuletzt vergebene ID (LastObjectID) gespeichert. Will ich nun eine neue ID vergeben lese ich eben diese aus. Vergebe die nächst höhere (also LastObjectID+1) an das Object, und schreibe den neuen Wert in die Datenbank.

Jetzt kann es aber sein, dass zwei Prozesse gleichzeitig ein Objekt erstellen. Also muss ich die Tabelle (oder am besten die Zeile) mit einem Lock sperren. Ich weiß aber nicht genau wie das in SQL funktioniert. Anscheinend kann ich immer nur für eine Transaktion sperren. Ich muss aber in der Transaktion auch auslesen und einen neuen Wert vergeben (ist also eine SELECT und eine UPDATE Aktion).

Zurzeit sieht das so aus:

Code: Alles auswählen

BEGIN WORK;
LOCK TABLE GlobalValues;
SELECT Value FROM "GlobalValues" WHERE Name='LastObjectID';
UPDATE "GlobalValues" SET Value=_Value_+1 WHERE Name='LastObjectID';
COMMIT WORK;"
Das Problem ist eben dass ich den Wert aus SELECT für die Ausführung des UPDATE-Kommandos benötige und in SQL gibt es ja nicht sowas wie Variablen. Vielleicht könnt ihr mir helfen?

schonmal danke für die Hilfe,
Halan
Despotist
Establishment
Beiträge: 394
Registriert: 19.02.2008, 16:33

Re: SQL Locks

Beitrag von Despotist »

Meine SQl-Zeit ist schon eine Weile her und beschränkt sich auch auf MS-Access Datenbanken und Ado.Net. Aber warum so umständlich? Soweit ich weiß lässt man idealerweise die Erzeugung der ID's die Datenbank selbst managen. Die kümmert sich um genau solche Dinge da zwar der Zugriff parallel erfolgen kann aber intern die Operationen atomar sind.
Ich weiß nicht ob das bei Postgre geht aber versuch mal bei der ID autoincrement einzustellen.
Ich hoffe das hilft dir weiter und geht nicht am Problem oder der Fragestellung vorbei.
Benutzeravatar
Top-OR
Establishment
Beiträge: 330
Registriert: 02.03.2011, 16:32
Echter Name: Jens H.
Wohnort: Esslingen/Dessau
Kontaktdaten:

Re: SQL Locks

Beitrag von Top-OR »

Moin,
ich muss sagen, dass PostgreSQL auch nicht mein zweiter Vorname ist, muss jedoch Despotist zustimmen: DAS ist eine AUFGABE des DBMS. Gibts da keine AutoIncrementfelder?
Die Datentypen serial und bigserial scheinen das zu sein.

Schau mal hier, evtl. hilft dir DAS weiter: http://www.pg-forum.de/sql/1100-umstieg ... ement.html

Wenn das nicht das Problem ist, würde ich mit Geschichten wie max(id)+1 im INSERT experimentieren.

Beste Grüße
--
Verallgemeinerungen sind IMMER falsch.
Benutzeravatar
Grimasso
Beiträge: 59
Registriert: 22.07.2010, 09:05

Re: SQL Locks

Beitrag von Grimasso »

Ja, mach das mit einer Datenbank Funktion. Sowas wird meisst als "auto increment", "generator" oder "sequence" bezeichnet. Musst mal etwas suchen - Habe leider auch keine Erfahrung mit PostgreSQL, kenne das aber von MySQL, Firebird und Oracle. Das hat vor allem den Vorteil, das diese Funktionen an der Transaktion vorbei arbeiten. Du kriegst also immer eine neue, eindeutige Nummer, auch wenn du alles in einer Transaktion verarbeitest. Würdest du mit select max(x) + 1 arbeiten, könnte es sein das du Daten eines anderen Users noch nicht siehst, weil er nicht committed hat und ihr am Schluss versucht die selbe ID zu speichern.
REVERT3D - 2.5d oldschool graphic/game engine http://revert3d.blogspot.com
odenter
Establishment
Beiträge: 207
Registriert: 26.02.2009, 11:58

Re: SQL Locks

Beitrag von odenter »

Jedes Statement ist transaktionssicher.

Du kannst von zwei Prozessen ohne Probleme INSERT-Statements auf die gleiche Tabelle absetzen, die DB kümmert sich um alles.
Ich hab mit PostrgeSQL nur mal rumgespielt, aber die Sequenzen sind ebenfalls transaktionssicher. Soll heissen zwei Prozesse, zwei INSERT's auf die gleiche Tabelle, ergeben auch zwei eindeutige ID's.

PostgreSQL ist ORACLE ziehmlich ähnlich.

EDIT:
http://www.postgresql.org/docs/8.1/stat ... uence.html

Die dort genannten/benutzen Funktionen sind ebenfalls wieder transaktionssicher.
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: SQL Locks

Beitrag von Halan »

Ahoi,

vielen Dank für die ganzen Tipps. Man merkt ich hab nicht so viel Ahnung von SQL :P

Werd das ganze mit Sequenzen umsetzten, scheint mir am einfachsten und sichersten.

Nochmal Danke,
Halan
Antworten