Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [PHP/MySQL] - commit klappt nicht (https://www.delphipraxis.net/152896-%5Bphp-mysql%5D-commit-klappt-nicht.html)

fkerber 11. Jul 2010 20:07

[PHP/MySQL] - commit klappt nicht
 
Hi!

Ich bin verwirrt.
Ich habe folgendes Statement:

PHP-Quellcode:
   $db -> autocommit(false);
   
   $sql2 = $db->prepare('SELECT active FROM course_registrations WHERE participantId=? AND courseId=?');
   $sql2 -> bind_param('ii', $participantID, $courseID);
   $sql2 -> execute();
   $sql2 -> bind_result($active);
   $sql2 -> fetch();

   if ($db -> commit()) {
      
   } else {
      //echo $active;
      echo "ARGH";
   }
Ein einfaches 0815-Select. Das Ganze soll in einer Transaktion laufen, mit was anderem zusammen, aber das ist hier unerheblich (will heißen, das andere geht einwandfrei - sicher!).
Aber das hier oben klappt nicht. Ich habe keine Idee mehr, woran es noch liegen könnte. Kopiere ich das Statement raus und schiebe es per phpMyAdmin in die DB läuft es einwandfrei. Selbst wenn ich mir $active ausgeben lasse (die Kommentarzeile einkommentiere), liefert es den richtigen Wert. Also klappt das Statement an sich ja?!
Im Error steht auch nix drin - ich verstehe die Welt nicht mehr (oder so ähnlich)...

Wer hilft mir vom Schlauch runter?


Liebe Grüße,
Frederic

mkinzler 11. Jul 2010 20:16

AW: [PHP/MySQL] - commit klappt nicht
 
Musst du die Transaktion vielleicht vorher starten?

fkerber 11. Jul 2010 20:22

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Nein, das muss man bei mysqli nicht machen.
Wie gesagt funktioniert es auch mit dem anderen Teil der TA und auch anderen, die ich verwende...


Liebe Grüße,
Frederic

mkinzler 11. Jul 2010 20:25

AW: [PHP/MySQL] - commit klappt nicht
 
Bei einem Select gibt es ja eigentlich auch nichts zum comitten

fkerber 11. Jul 2010 20:32

AW: [PHP/MySQL] - commit klappt nicht
 
Das habe ich mir auch schon gedacht.
Ich erzähl mal die ganze story.

Ich mach ein Update in der DB und möchte dann den geänderten Wert auslesen.
Das muss ich zusammen in einer Transaktion machen, damit mir keiner dazwischen fummeln kann.

Und das muss ja irgendwie gehen...
Aber wenn das SELECT drin ist, gehts schief...

Oder gibt es einen anderen Weg?


Liebe Grüße,
Frederic

alcaeus 11. Jul 2010 21:04

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von fkerber (Beitrag 1034845)
Ich mach ein Update in der DB und möchte dann den geänderten Wert auslesen.
Das muss ich zusammen in einer Transaktion machen, damit mir keiner dazwischen fummeln kann.

In so einem Fall verwendet man LOCK TABLES, nicht Transaktionen. Transaktionen verwendest du wenn du mehrere Updates/Inserts machen musst, die allerdings eine Einheit bilden und deswegen entweder komplett oder gar nicht geschrieben werden.

Greetz
alcaeus

mkinzler 11. Jul 2010 21:11

AW: [PHP/MySQL] - commit klappt nicht
 
Es scheint ihm eher darum zu gehen, sicherzustellen, den geänderten Satz zu bekommen.
Das sollte mit last_inserted_id() gehen ( auch wenn der Name der Funktion es nicht unbedingt Erraten lässt)

fkerber 11. Jul 2010 21:14

AW: [PHP/MySQL] - commit klappt nicht
 
Hi,

hmm, gibt es da wirklich keine andere Möglichkeit?
Wenn ich die Doku richtig lese, habe ich ja nur die Möglichkeit, die komplette Tabelle zu locken.

Das ist ja doch schon deutlich "härter", als im Rahmen einer TA, die ja deutlich feinkörniger arbeiten kann...

@Markus:
last_insert_id funktioniert nur bei auto_inc Feldern und (wie der Name doch vermuten lässt ;) ) nur bei Inserts - zumindest laut Doku.
Außerdem brauche ich auch nicht die id, sondern ein anderes Feld.


Liebe Grüße,
Frederic

mkinzler 11. Jul 2010 21:19

AW: [PHP/MySQL] - commit klappt nicht
 
Dann frag halt die Updatebedingung im Select ab

fkerber 11. Jul 2010 21:20

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Wie meinst du?
In welchem Select soll ich was fragen?


Liebe Grüße,
Frederic

mkinzler 11. Jul 2010 21:23

AW: [PHP/MySQL] - commit klappt nicht
 
SQL-Code:
Select Active from course_registrations WHERE <Bedingung des Updatebefehls>;

alcaeus 11. Jul 2010 21:24

AW: [PHP/MySQL] - commit klappt nicht
 
Moin,

also, wenn du einen Update und anschliessenden Select machst und nicht willst, dass da ein anderer Update-Prozess dazwischenkommt, dann musst du definitiv mit Locks arbeiten. Transaktionen sind nur fuer Inserts und Commits, und ohne Locks kann dir ein anderer Update-Prozess dazwischenfunken.
Je nach Anwendungsfall ist es aber besser, den finalen Wert anzuzeigen, also inkl. eines eventuellen zwischenzeitlichen Updates.

Greetz
alcaeus

fkerber 11. Jul 2010 21:28

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Das ist doch exakt das, was ich oben tue?!
Nur genau das funktioniert ja nicht.
Oder zumindest führt es dazu, dass die Transaktion failed und dann ein rollback macht.

@alcaeus:
Ok, "schade"
Und es gibt auch keinen feinkörnigeren Lock als gleich die ganze Tabelle?
Den finalen Wert hier auszugeben, ist leider keine Option an dieser Stelle. Ich muss gezielt dieses Update reflektieren.

Grüße,
Frederic

mkinzler 11. Jul 2010 21:30

AW: [PHP/MySQL] - commit klappt nicht
 
Ist es denn sehr wahrscheinlich, dass jemand anderes genau diesen Satz gleichzeitig updatet?

fkerber 11. Jul 2010 21:32

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

In der Vergangenheit hat sich gezeigt, dass Nutzer dazu neigen, Links mit Doppelklicks auszuführen und da sind schon komische Konstellationen zustande gekommen.
Ich kann nicht genau sagen, ob es damit zu lösen ist, aber ich will es so fehlerfrei wie irgend möglich machen.


Grüße,
Frederic

mkinzler 11. Jul 2010 21:34

AW: [PHP/MySQL] - commit klappt nicht
 
Bei einem Doppelklick würde dsann aber 2 Mal der selbe Updatebefehl durchgeführt

himitsu 11. Jul 2010 21:34

AW: [PHP/MySQL] - commit klappt nicht
 
Werden diese MultiQuery zusammen verarbeitet oder kann da eine andere Abfrage dazwischenfunken?

http://www.phpbuddy.eu/mysqli-erweit...5.html?start=5

fkerber 11. Jul 2010 21:37

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Nein, leider nicht:

SQL-Code:
UPDATE course_registrations SET active = NOT active WHERE participantId=? AND courseId=?


@himitsu:
Nach meinem Kenntnisstand ist das nicht transaktionssicher.

Grüße, Frederic

alcaeus 11. Jul 2010 21:38

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von fkerber (Beitrag 1034858)
@himitsu:
Nach meinem Kenntnisstand ist das nicht transaktionssicher.

Korrekt.

Greetz
alcaeus

mkinzler 11. Jul 2010 21:38

AW: [PHP/MySQL] - commit klappt nicht
 
Na dann ist das natürlich ungeschickt

alcaeus 11. Jul 2010 21:47

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von fkerber (Beitrag 1034853)
Und es gibt auch keinen feinkörnigeren Lock als gleich die ganze Tabelle?

Habs mir gerade nochmal angesehn: nein. Row-Level-Locks werden nur von InnoDB unterstuetzt, wenn du dich auf das Locking der DB verlaesst.
Bei READ gibt es die Moeglichkeit, so genannte "non-conflicting inserts" zu erlauben, write-Locks gelten aber immer fuer die ganze Tabelle. Da du hier aber eine relativ kurze und unkritische Critical Section hast, duerfte ein Table-Lock erst bei hoher Last auffallen. Du hast schliesslich keine Key-Updates, und wenn die Where-Bedingung von Update und Select als gesamter Key vorhanden sind, gibt es da wirklich keine Performance-Probleme.

Greetz
alcaeus

fkerber 11. Jul 2010 21:50

AW: [PHP/MySQL] - commit klappt nicht
 
Hi,

Zitat:

Zitat von alcaeus (Beitrag 1034861)
Habs mir gerade nochmal angesehn: nein. Row-Level-Locks werden nur von InnoDB unterstuetzt, wenn du dich auf das Locking der DB verlaesst.

danke für deine Mühe. Es ist ne InnoDB, aber ich vermute, deine Aussage sagt, das ist nur was DB-internes, was ich von außen nicht anleiern kann?


Liebe Grüße,
Frederic

alcaeus 11. Jul 2010 22:03

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von fkerber (Beitrag 1034862)
danke für deine Mühe. Es ist ne InnoDB, aber ich vermute, deine Aussage sagt, das ist nur was DB-internes, was ich von außen nicht anleiern kann?

Korrekt - das betrifft nur die von InnoDB selbst initiierten Locks.

Greetz
alcaeus

fkerber 11. Jul 2010 22:06

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Gut, soweit ;)

Jetzt sehe ich nur ein Problem:
Die Doku sagt:
Zitat:

Die korrekte Vorgehensweise bei der Verwendung von LOCK TABLES in Verbindung mit transaktionssicheren Tabellen wie InnoDB besteht darin, AUTOCOMMIT = 0 zu setzen und UNLOCK TABLES erst dann aufzurufen, wenn die Transaktion explizit übergeben werden soll. Wenn Sie LOCK TABLES aufrufen, setzt InnoDB intern eine eigene Tabellensperre. Auch MySQL setzt eine eigene Tabellensperre. InnoDB hebt seine Sperre beim nächsten Commit-Vorgang auf; damit MySQL seinerseits die Sperre aufhebt, müssen Sie UNLOCK TABLES aufrufen. Sie sollten AUTOCOMMIT = 1 nicht setzen, weil InnoDB dann seine Tabellensperre direkt nach dem Aufruf von LOCK TABLES aufhebt; auf diese Weise kann es zu einer vollständigen Sperrung kommen. Beachten Sie, dass bei AUTOCOMMIT = 1 die InnoDB-Tabellensperre überhaupt nicht gesetzt wird, damit ältere Anwendungen sich nicht versehentlich vollständig ausschließen.
D.h. doch ich muss alles so machen wie bisher auch und zusätzlich das LOCK TABLES da rein. Rettet das mich dann wirklich? Oder fliegt mir die Sache dann trotzdem um die Ohren? Weil das Select wäre ja weiter dann in der Transaktion da drin?!

Grüße, Frederic

alcaeus 11. Jul 2010 22:13

AW: [PHP/MySQL] - commit klappt nicht
 
Moin,

ganz kurz das Prozedere:
SQL-Code:
SET AUTOCOMMIT = 0;
LOCK TABLES course_registrations WRITE;
UPDATE course_registrations...;
SELECT active FROM course_registrations...;
UNLOCK TABLES course_registrations;
SET AUTOCOMMIT = 1;
Ich bin mir grad nicht ganz sicher wie das Verhalten bei autocommit = 0 ist - eventuell musst du nach dem Update aber noch vor dem Select einen Commit machen bzw. auch vor dem Update noch eine Transaktion oeffnen. Ganz aussen rum ist der autocommit, dann dein Lock, anschliessend die Queries die du ausfuehren willst.

Beachte aber, dass du den Unlock direkt nach dem Select machst und noch bevor du die Daten verarbeitest, damit du die Tabelle nicht laenger als noetig benutzt. Beachte ausserdem dass du vor dem Unlock keine Tabelle benutzen kannst die nicht vorher gelockt wurde.

Greetz
alcaeus

mkinzler 11. Jul 2010 22:22

AW: [PHP/MySQL] - commit klappt nicht
 
Das Transaktionshandling bei MySQL erscheint mir etwas umständlich und suboptimal

alcaeus 11. Jul 2010 22:29

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von mkinzler (Beitrag 1034870)
Das Transaktionshandling bei MySQL erscheint mir etwas umständlich und suboptimal

Du solltest wissen dass solche Aussagen ohne Begruendung wertlos sind. Wenn man das System verstanden hat ist dieses Vorgehen vollkommen normal.

Greetz
alcaeus

mkinzler 11. Jul 2010 22:30

AW: [PHP/MySQL] - commit klappt nicht
 
Sorry dass ich mir überhaupt erlaubt habe etwas zu schreiben.

fkerber 11. Jul 2010 22:32

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Irgendwo muss ein Haken sein:

PHP-Quellcode:
   $db -> autocommit(false);
   $db -> query("LOCK TABLES course_registrations WRITE");
   
   $sql = $db -> prepare('UPDATE course_registrations SET active = NOT active WHERE participantId=? AND courseId=?');
   $sql -> bind_param('ii', $participantID, $courseID);
   $sql -> execute();
   
   $sql2 = $db->prepare('SELECT active FROM course_registrations WHERE participantId=? AND courseId=?');
   $sql2 -> bind_param('ii', $participantID, $courseID);
   $sql2 -> execute();

   $db -> query("UNLOCK TABLES course_registrations");

   $sql2 -> bind_result($active);
   $sql2 -> fetch();

   if ($db -> commit()) {
      
   } else {
      echo $active;      
      echo "ARGH";
   }


   //$db -> query("UNLOCK TABLES course_registrations");

   
   $db -> autocommit(true);
Egal an welchen der beiden Stellen das UNLOCK steht - das Ergebnis ist immer ein ARGH...


Grüße, Frederic

alcaeus 11. Jul 2010 22:44

AW: [PHP/MySQL] - commit klappt nicht
 
Zitat:

Zitat von mkinzler (Beitrag 1034873)
Sorry dass ich mir überhaupt erlaubt habe etwas zu schreiben.

Komm, du solltest besser wissen als auf beleidigt zu spielen :roll:
Es ist nunmal einfach etwas "unlogisch", "kompliziert", "doof", "ungeschickt", was auch immer zu nennen. Wenn du die letzten paar PHP-Themen hier in der DP ansatzweise verfolgt hast weisst du auch was dabei rauskommt: irgendwer liest es und nimmts fuer bare Muenze.

Es spricht nichts gegen eine Diskussion ueber das Thema - aber wenn dann bitte mit Argumenten.

Zum Thema:
1. Den fetch() solltest du vor dem Unlock ausfuehren.
2. Die Logik hat nen kleinen Denkfehler: wenn autocommit = 0 musst du das Update-Statement mit nem Commit bestaetigen. Das musst du vor dem Select machen, ansonsten ist die Aenderung ja noch nicht in der DB.

Greetz
alcaeus

fkerber 11. Jul 2010 23:27

AW: [PHP/MySQL] - commit klappt nicht
 
Hi!

Ja, da habe ich natürlich jetzt auf dem Schlauch gestanden.
Danke dir fürs runterheben ;)

Die augenscheinlich funktionierende Version sieht jetzt so aus:

PHP-Quellcode:
$db -> autocommit(false);
   $db -> query("LOCK TABLES course_registrations WRITE");
   
   $sql = $db -> prepare('UPDATE course_registrations SET active = NOT active WHERE participantId=? AND courseId=?');
   $sql -> bind_param('ii', $participantID, $courseID);
   $sql -> execute();
   
   if ($db -> commit() && $sql -> affected_rows == 1) {

      $sql -> close();
      $sql2 = $db->prepare('SELECT active FROM course_registrations WHERE participantId=? AND courseId=?');
      $sql2 -> bind_param('ii', $participantID, $courseID);
      $sql2 -> execute();
      $sql2 -> bind_result($active);
      $sql2 -> fetch();
      $sql2 -> close();
      $db -> query("UNLOCK TABLES");
      $db -> autocommit(true);
      
      
      $owner = getLeaderForCourseId($db, $courseID);
      sendMessage($db,
               $owner,   
               $participantID,
               $active?20:21,
               $active?$langActivated:$langDeactivated,
               $_GET['cid']);
      return 1;
   } else {
      $sql -> close();
      $db -> query("UNLOCK TABLES");
      $db -> autocommit(true);
      return 0;
   }
Vllt. magst du ja nochmal drüberschauen und sagen, ob es noch was zu verbessern gibt.

Liebe Grüße,
Frederic


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz