Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
(Web-) Design und webbasierte Sprachen Tipps & Tricks, Designabgleich, HTML & Javascript, Flash, ASP, PHP, Perl/CGI...

PHP & PostgreSQL-Transactions

Diskussion: PHP & PostgreSQL-Transactions im Forum (Web-) Design und webbasierte Sprachen, in der Kategorie Web, Network & Multimedia Palace; Anzeige Hi, Ich bastle gerade an einer kleinen Web-App, bei der (mehrere) Benutzer gleichzeitig an einer Datenbank arbeiten. Jeder soll ...

Antwort
Alt 06.08.09, 10:46   #1 (permalink)
 
Registriert seit: 15.12.05
vis.p Leistung: Facit NTK
vis.p eine Nachricht über ICQ schicken
Likes: 0
PHP & PostgreSQL-Transactions

Anzeige

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)

PHP-Code:
<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:[list=1][*]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
vis.p ist offline   Mit Zitat antworten
Alt 06.08.09, 16:19   #2 (permalink)
sw33tlull4by
Guest
 
Likes:
Standard

Ich kenne CakePHP ueberhaupt nicht, und habe auch noch nie was mit PostgreSQL gemacht, aber ich hab eine Ahnung.
Mal ganz abgesehen davon das die Schreib und Leselocks fehlen, welche eine Transaktion eigentlich auch beinhalten muessen(werden evtl von BEGIN gesetzt,ka), passiert glaube ich folgendes:

Du machst insert und Rolleback.
Eine Verbindung,Server weiss was getan wurde, und kann es rückgängig machen.
Du machst ein Insert, das Skript laeuft durch, und beim nächsten mal machst du ein Rolleback, was nun passiert ist, das das DBMS nicht weiss was es zurrueck nehmen soll, da neue Verbindung.
mfg

sw33t
  Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 06.08.09, 18:24   #3 (permalink)
Themenstarter
 
Registriert seit: 15.12.05
vis.p Leistung: Facit NTK
vis.p eine Nachricht über ICQ schicken
Likes: 0
Standard

Danke für die Antwort!

Ich denke auch nicht, dass es an CakePHP liegt, da es schon in diesem Bsp ohne Cake nicht funktioniert =/

Zitat:
Du machst insert und Rolleback.
Eine Verbindung,Server weiss was getan wurde, und kann es rückgängig machen.
Du machst ein Insert, das Skript laeuft durch, und beim nächsten mal machst du ein Rolleback, was nun passiert ist, das das DBMS nicht weiss was es zurrueck nehmen soll, da neue Verbindung.
Ja ich fürchte das ist das Problem. Deswegen hab ich das auch mit einer persistenen Verbindung probiert (pg_pconnect anstelle von pg_connect), aber auch kein Erfolg.
Gibt es irgendeine Möglichkeit das mit Transactions zu realisieren oder sollte ich umdenken und eine eigene Lösung programmieren?
vis.p ist offline   Mit Zitat antworten
Alt 06.08.09, 18:53   #4 (permalink)
Moderator
 
Benutzerbild von lightsaver
 
Registriert seit: 19.06.06
lightsaver Leistung: Pentium Ilightsaver Leistung: Pentium Ilightsaver Leistung: Pentium I
Likes: 52
Standard

Hast du dir mal die Tipps der User auf http://www.php.net/manual/de/function.pg-pconnect.php durchgelesen? Da war einmal ein anderes Connection-pooling und dann noch die Benutzung einer Klasse vorgeschlagen. Probier das doch mal
lightsaver ist offline   Mit Zitat antworten
Alt 06.08.09, 23:12   #5 (permalink)
Senior Member
 
Benutzerbild von odigo
 
Registriert seit: 25.12.04
odigo Leistung: 8086odigo Leistung: 8086
odigo eine Nachricht über ICQ schicken
Likes: 54
Standard RE: PHP & PostgreSQL-Transactions

Zitat:
Original von vis.p
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).
Ganz ehrlich, dein ganzes Vorgehen ist zugebenermaßen eine suboptimale Idee ums mal nett auszudrücken. Schon mal was von Lost Updates gehört? Oder das große Transaktionen Gift sind für eine performante Anwendung? Nur mal die Spitze des Eisbergs zu erwähnen. Ich finde diese Art von Softwareentwicklung sollte man sich erst gar nicht angewöhnen.

odigo
odigo ist offline   Mit Zitat antworten
Alt 07.08.09, 10:08   #6 (permalink)
sw33tlull4by
Guest
 
Likes:
Standard

Da wäre auch noch das Phänomen des Phantom, aber egal...

Das mit der Klasse wird nicht so funktioniere, da man in PHP keine Ressourcesn speichern kann, und eine Verbindung gilt in PHP als eine Ressource und die kannst du nun mal nicht im $_SESSION-array speichern.

Ich hatte mal ein ähnliches Problem.
Bei mir lag der Fall aber so, das ich eine feste Anzahl von Tables hatte, aber ich nur eine bestimmte Klasse von Einträgen, wegen Datenkonsistens, nicht freigeben wollte.

Problem habe ich dadurch geloest das ich die Schluessel der Einträge in eine weitere Tabelle geschrieben habe, und ich die Einträge dann nur zum Zugriff freigab wenn sie nicht in der Tabelle standen.
mfg

sw33t
  Mit Zitat antworten
Alt 07.08.09, 12:49   #7 (permalink)
Themenstarter
 
Registriert seit: 15.12.05
vis.p Leistung: Facit NTK
vis.p eine Nachricht über ICQ schicken
Likes: 0
Standard

Ja, dass das eine suboptimale Idee ist hab ich befürchtet...hat vom Prinzip her recht einfach ausgesehen. Was wäre z.B. wenn User A einen Eintrag ändert und User B ihn in seiner Transaktion löscht? Gibt dabei wohl zuviele Probleme...

Jetzt bleibt mir nur es entweder selbst zu programmieren (extra Tabelle), oder auf das Feature zu verzichten

Sollte ich es mit der Tabelle lösen, werde ich gern den Weg hier posten.

Danke!
vis.p ist offline   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Web, Network & Multimedia Palace » (Web-) Design und webbasierte Sprachen » PHP & PostgreSQL-Transactions
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
postgresql? Seo Linux/UNIX 1 18.05.03 22:13


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61