Nebenläufigkeit kontrollieren in Postgres

Kirby.exe

Top Contributor
Also irgendwie bin ich sehr verwirrt...Wir sollen ein psql Skript "korrigieren" sodass die Nebenläufigkeit hier keine Probleme macht. Dazu wurde das "Schlüsselwort" SET TRANSACTION von Postgres genannt, jedoch verstehe ich nicht ganz wie der Kram funktioniert...Ich habe das so verstanden, dass man für jeden Thread eine Transaction erstellt und so gleichzeitigen Zugriff auf die selbe Tabelle verhindert.

Jedoch vermute ich, dass dies falsch ist, denn mein Skript funktioniert nicht xD
Bash:
PSQL='psql -U aphbr -h localhost -p 5435'

$PSQL -c 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;'
$PSQL -c 'DROP TABLE IF EXISTS t;'
$PSQL -c 'CREATE TABLE t (s NUMERIC);'
$PSQL -c 'INSERT INTO t VALUES (0);'

for i in ‘seq 1 100‘
do
    $PSQL -c 'BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; INSERT INTO t VALUES (1+(SELECT MAX(s) FROM t)); COMMIT TRANSACTION;' &
done

Hier ist der Link zu den Docs von Set Transactions
 

mihe7

Top Contributor
Die Zeile 3 ist natürlich für die Tonne. Du startest eine Session (psql), dort eine Transaktion und dann wird die Session beendet, womit auch die Transaktion beendet wird. Zeile 10 sieht besser aus, allerdings wird repeatable read nicht reichen. Werden die Anweisungen innerhalb eines kurzen Zeitraums ausgeführt, lesen mehrere Transaktion ggf. das gleiche Maximum aus der Tabelle.
 

Kirby.exe

Top Contributor
Funktioniert SERIALIZABLE nicht?!?
Nope da kommt ne saftige Fehlermeldung

Code:
kirby@kirby: ./scripty.sh
SET
DROP TABLE
CREATE TABLE
INSERT 0 1
kirby@kirby:$ ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.
ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during write.
HINT:  The transaction might succeed if retried.
COMMIT

Hier nochmal der Code :

Bash:
PSQL='psql -U aphbr -h localhost -p 5435'

$PSQL -c 'SET STATEMENT_TIMEOUT = 600000;'
$PSQL -c 'DROP TABLE IF EXISTS t;'
$PSQL -c 'CREATE TABLE t (s NUMERIC);'
$PSQL -c 'INSERT INTO t VALUES (0);'

for i in ‘seq 1 100‘
do
    $PSQL -c 'BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; INSERT INTO t VALUES (1+(SELECT MAX(s) FROM t)); COMMIT TRANSACTION;' &
done
 

mihe7

Top Contributor
Das ist doch richtig. Du hast keine doppelten Werte in der Tabelle, die betreffenden Transaktionen schlagen fehl (ACID-Eigenschaft). Wenn Du willst, dass das einfach durchläuft, dann würde ich Sperren verwenden, also vor dem INSERT noch ein LOCK TABLE t; einfügen.
 

mihe7

Top Contributor
So:
Code:
SET
DROP TABLE
CREATE TABLE
INSERT 0 1
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT
COMMIT

real    0m1.267s
user    0m4.035s
sys    0m2.286s

PSQL='psql -U postgres'

$PSQL -c 'SET STATEMENT_TIMEOUT = 600000;'
$PSQL -c 'DROP TABLE IF EXISTS t;'
$PSQL -c 'CREATE TABLE t (s NUMERIC);'
$PSQL -c 'INSERT INTO t VALUES (0);'

for i in $(seq 1 100)
do
$PSQL -c 'BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; LOCK TABLE t; INSERT INTO t VALUES (1+(SELECT MAX(s) FROM t)); COMMIT TRANSACTION;' &
done

wait $(jobs -p)

Das läuft bei mir in einem Docker-Container.
 

mihe7

Top Contributor
Vermutlich: $(seq 1 100) statt `seq 1 100`; letzteres wurde bei mir als String verarbeitet, d. h. für "seq", "1" und "100" wurde je eine Iteration durchgeführt - das würde dann auch die 3 Datensätze erklären.
 

Kirby.exe

Top Contributor
Vermutlich: $(seq 1 100) statt `seq 1 100`; letzteres wurde bei mir als String verarbeitet, d. h. für "seq", "1" und "100" wurde je eine Iteration durchgeführt - das würde dann auch die 3 Datensätze erklären.
bruh xD ich sollte echt meine bash kenntnisse verbessern xD des stand so auf dem PDF xD Ich dachte mhh wird schon stimmen xD

Was lernt man daraus...Was man nicht kennt wird bei Google reingehackt xD
 

Ähnliche Java Themen


Oben