Ich hab ein großes Verständnisproblem mit Transaktionen:
Ich mache folgenden Ablauf:
SESSION 1:
BEGIN;
SESSION 2:
BEGIN;
UPDATE foo SET zahl = zahl + 20;
SESSION 1:
UPDATE foo SET zahl = zahl + 20;
SESSION 2:
COMMIT;
SESSION 1:
COMMIT;
Laut meinem Buch sollte jetzt eine Inkonsistenz bestehen - was meiner Meinung nach so viel bedeutet dass bei einem Startwert von 100 beide auf 120 setzen - und nicht wie gewünscht 140.
Das soll der Fall sein wegen READ COMMITTED
Bei mir kommt es aber ganz anders: Das Update in SESSION 1 blockiert so lange bis ich in SESSION 2 commite :-S
Warum das? Wäre das nicht das Verhalten von SERIALIZABLE?
Bei mir kommt es aber ganz anders: Das Update in SESSION 1 blockiert so lange bis ich in SESSION 2 commite :-S
Warum das? Wäre das nicht das Verhalten von SERIALIZABLE?
Danke im Voraus
lg
SERIALIZABLE würde auch blockieren, allerdings würde dann die TX, die zuerst commited, gewinnen und die andere einen Fehler bekommen: “ERROR: could not serialize access due to concurrent update”.
Eine Frage hätte ich noch:
Ich hab folgenden Table:
bookid => integer
bookname => text
Nun habe ich einen Datensatz drin: bookid=1 bookname=‘buch 1’
Ohne jetzt serial zu verwenden (bewusst):
BEGIN;
LOCK TABLE books;
INSERT INTO books VALUE((SELECT MAX(bookdid) + 1), ‘buch2’);
COMMIT;
Das Problem ist ja, dass SELECT MAX(…) in mehreren Sessions “1” als ID zurückliefern kann
Nun meine Fragen:
Angenommen das LOCK TABLE ist nicht da: habe ich die Garantie dass dieses Statement atomar ausgeführt wird?
Brauche ich hier den vollen “ACCESS EXCLUSIVE MODE”?
In meinem Buch ist ein Beispiel wo Rechnungen etc fürn Versand erstellt werden. Der Autor benutzt “LOCK TABLE … IN SHARE MODE” mit dem Kommentar “Tabelle … gegen Änderungen sperren”.
Wenn nun aber 2 Tabellen im SHARE MODE locken ohne SELECT oder INSERT zu machen habe ich ja einen Deadlock. Sollte man da net einen SHARE ROW EXCLSUIVE MODE machen?
Hmm. Damit kann ich aber mein Problem aus Post#6 nicht lösen oder?
SELECT FOR UPDATE verhindert ja nur ein ändern - aber das SELECT geht ja noch immer und beide würden den gleichen Datensatz bekommen. Besser zu sehen hier (geschrieben in plpgsql):
DECLARE
myMaxID INT4;
BEGIN
SELECT MAX(bookid) + 1 INTO myMaxID FROM bookatble;
…
END;
Nun wird die Funktion angenommen 2 Mal parallel aufgerufen - nun hat myMaxID 2 Mal die Zahl “4” - ich hätte somit 2 Bücher mit der ID 4.