2010-11-01 12 views
7

worden meinen Kopf für eine Weile auf dem Kratzen ....PDO :: ATTR_AUTOCOMMIT ignoriert nicht transaktions INSERT/UPDATE

ich ein PDO-Objekt mit pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); habe, wie ich FOR UPDATE mit einigen InnoDB-Tabellen verwenden mag. Das Lesen der MySQL-Dokumentation wird FOR UPDATE nur sperren gelesenen Zeilen, wenn:

  1. Sie in einer Transaktion sind
  2. Sie sind nicht in einer Transaktion und set autocommit=0 hat

So erteilt worden, ich bin Verwenden Sie ATTR_AUTOCOMMIT, damit das PDO-Objekt Zeilen sperren kann. In beiden Fällen führt dies dazu, dass INSERT- und UPDATE-Anweisungen nicht angewendet werden. Diese Anweisungen haben nichts mit FOR UPDATE zu tun, sie laufen nur durch das gleiche PDO-Objekt mit vorbereiteten Anweisungen.

Meine MySQL-Query-Log wie folgt aussieht:

xxx Connect [email protected] 
xxx Query  set autocommit=0 
xxx Query  INSERT INTO foo_tbl (bar, baz) VALUES ('hello','world') 
xxx Quit 

PHP/PDO nicht beschweren, aber aus der Tabelle auswählen zeigt, dass die Daten geschrieben worden ist.

Die Abfragen, die ich ausgeführt habe, wurden Tausende von Zeit zuvor ausgeführt; nur die ATTR_AUTOCOMMIT Änderung wurde vorgenommen. Wenn Sie diese Option entfernen, funktioniert alles wieder. Transaktionen funktionieren auch mit der Option autocommit=0.

Gibt es weitere Aufrufe, die auf dem PDO-Objekt (commit() beklagt zu Recht, dass es nicht in einer Transaktion ist) machen müssen, um die Änderungen zu machen? Grundsätzlich möchte ich ein einfaches PDO-Objekt, aber mit der Option, Zeilen außerhalb von Transaktionen für InnoDB-Tabellen zu sperren (der Hintergrund dafür ist zu lang und langweilig für hier).

Ich bin sicher, dass dies etwas dumm ist mir fehlt Kratzer Kopf

+0

Keine Sorge, wir alle vermissen manchmal Dinge! Ich weiß, es passiert mir viel mehr als ich zugeben möchte :-) – Josh

Antwort

6
$db = new PDO('mysql:dbname=test'); 
    $db->setAttribute(PDO::ATTR_AUTOCOMMIT,0); 
    var_dump($db->query('SELECT @@autocommit')->fetchAll()); //OK 
    $db->query("INSERT INTO foo (bar) VALUES ('a');"); 
    $db->query("COMMIT;");//do by SQL rather then by interface/PDO-method 

Aber im Grunde sind Sie in einer Transaktion ein Rollback usw. (Sie haben einfach nicht mit PDO gestartet) Es ist auch noch verfügbar. Es ist durchaus fraglich, ob das ein Fehler ist (commit() nicht direkt anrufen).

+0

+1 - Ich würde sagen, es ist ein Bug ... aber hey, es gibt höhere Prioritäten bei der Diskussion über Borked PHP API: P Gute Antwort. –

+0

Es ist kein Fehler, es ist nur ein irreführender Name, da viele Leute das Wort "commit" mit Transaktionen verknüpfen. Es bedeutet nicht, dass Ihre ausstehenden Transaktionen automatisch committen oder nicht, es bedeutet nur, ob Ihre Abfragen, die nicht durch Transaktionen gestartet werden, automatisch "commited" werden oder nicht, was sie standardmäßig sind. Technisch starten Ihre Verbindungen eine Transaktion, wenn sie deaktiviert ist . –