Hi,
Ich bastle gerade an einer kleinen Web-App, bei der (mehrere) Benutzer gleichzeitig an einer Datenbank arbeiten. Jeder soll dabei aber in einer Transaction arbeiten, die während seiner Session mitläuft. Am Ende soll er dann selbst entscheiden können, ob er die Änderungen übernimmt (COMIMT) oder verwirft (ROLLBACK).
Ich habe das Problem mal testweise (verwende eigentlich CakePHP) in ein einfaches PHP-Skript heruntergebrochen.
Nicht abschrecken lassen. Das Skript ist eingentlich ganz einfach =)
(Erklärung folgt nach dem Code)
Ablauf:
Ich bastle gerade an einer kleinen Web-App, bei der (mehrere) Benutzer gleichzeitig an einer Datenbank arbeiten. Jeder soll dabei aber in einer Transaction arbeiten, die während seiner Session mitläuft. Am Ende soll er dann selbst entscheiden können, ob er die Änderungen übernimmt (COMIMT) oder verwirft (ROLLBACK).
Ich habe das Problem mal testweise (verwende eigentlich CakePHP) in ein einfaches PHP-Skript heruntergebrochen.
Nicht abschrecken lassen. Das Skript ist eingentlich ganz einfach =)
(Erklärung folgt nach dem Code)
PHP:
<pre>
<?
function query ($c, $sql) {
(pg_query($c, $sql) === false) ? "Query ($sql) ERROR" : "Query ($sql) OK";
}
$conn = "host='localhost' port='5432' dbname='lists' ";
$conn .= "user='xxx' password='xxx'";
//$connection = pg_connect($conn, PGSQL_CONNECT_FORCE_NEW);
$connection = pg_pconnect($conn); //Persistent
if ($connection) {
echo "Connected successfully!\n";
pg_query($connection, "SET search_path TO public");
}
//Check transaction state
echo "PostgreSQL Transaction Status:\nActive " . PGSQL_TRANSACTION_ACTIVE;
echo "\nIDLE " . PGSQL_TRANSACTION_IDLE;
echo "\nINERROR " . PGSQL_TRANSACTION_INERROR;
echo "\nINTRANS " . PGSQL_TRANSACTION_INTRANS;
echo "\nUknown " . PGSQL_TRANSACTION_UNKNOWN;
echo "\n\nStatus(before)=" . pg_transaction_status($connection) . "\n";
switch($_GET['c']) {
case 'begin':
query($connection, "BEGIN;");
break;
case 'insert':
query($connection, "INSERT INTO list (name, text) VALUES('test', 'transaction');");
break;
case 'rollback':
query($connection, "ROLLBACK;");
break;
case 'commit':
query($connection, "COMMIT;");
break;
case 'bic':
query($connection, "BEGIN;");
query($connection, "INSERT INTO list (name, text) VALUES('test', 'transaction');");
query($connection, "COMMIT;");
break;
case 'bir':
query($connection, "BEGIN;");
query($connection, "INSERT INTO list (name, text) VALUES('test', 'transaction');");
query($connection, "ROLLBACK;");
break;
default:
echo "\nplease click one of the links below";
break;
}
//Check transaction state
echo "\n\nStatus(after)=" . pg_transaction_status($connection);
?>
</pre>
<a href="?c=begin">Begin</a><br>
<a href="?c=insert">Insert</a><br>
<a href="?c=rollback">Rollback</a><br>
<a href="?c=commit">Commit</a><br>
<hr>
<a href="?c=bic">Begin, Insert & Commit</a><br>
<a href="?c=bir">Begin, Insert & Rollback</a><br>
Ablauf:
- Verbindungsaufbau (Entweder persistent oder nicht, je nach aktiver pg_*connect-Zeile)
- Anzeigen des Transaction-State
- Durchführen der gewählten Operation
- Erneutes anzeigen des Transaction-State
[/list=1]
Es gibt folgende Operationen:- Transaction beginnen
- Datensatz speichern
- Commit
- Rollback
Und dann gibt es noch 2 zusätzliche Ops für Begin, Insert & Commit/Rollback.
So nun zum Problem ?(
Gewünschtes Verhalten wäre, dass man zuerst Beginn drückt, dann im nächsten Aufruf Insert, dann Rollback und im Nachhinein wäre der neue Eintrag nicht in der Datenbank zu sehen...tatsächlich scheint mir die Transaction am Seitenende flöten zu gehen und der Eintrag steht nach dem Rollback immernoch drin
Das Begin, Insert & Rollback (in einem) funktioniert nämlich wie gewünscht.
Wie komme ich dorthin?
Scheut euch nicht zu antworten, auch nur um mir zu sagen, dass ich auf dem Holzweg bin
mfg
Nachtrag - die Versionen:
XAMPP (Apache 2.2.11, PHP 5.2.8)
PostgreSQL 8.3.5