2010-09-01 7 views
6

Ich habe zwei komplizierte PHP-Objekte, von denen jedes Daten in ein paar MySQL-Tabellen enthält.Wie kann ein PHP-PDO-Objekt herausfinden, ob es bereits in einer MySQL-Transaktion ist?

Manchmal muss ich nur ein Objekt A aus der Datenbank entfernen, und das dauert 3 SQL-Anweisungen.

Manchmal muss ich ein Objekt B aus der Datenbank entfernen, das dauert 4 SQL-Anweisungen, und die auch muss alle Objekte des Objekts A finden und entfernen, die das Objekt B besitzt.

Also innerhalb der Funktion delete_A(), führe ich diese Anweisungen innerhalb einer Transaktion. Innerhalb der Funktion, die delete_B(), möchte ich eine große große Transaktion ausführen, die die Aktivitäten innerhalb von delete_A() abdeckt. Wenn das gesamte Atom, das ein B löscht, fehlschlägt, muss ich alle seine A's im Rollback wiederherstellen.

Wie aktualisiere ich die Definition von delete_A(), um nur eine neue Transaktion zu öffnen, wenn nicht bereits eine größere Transaktion ausgeführt wird.

ich voraussichtlich in der Lage sein, so etwas zu tun, aber das autocommit Attribut scheint nicht von beginTransaction()

function delete_A($a){ 
    global $pdo; 
    $already_in_transaction = !$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT); 
    if(!$already_in_transaction){ 
    $pdo->beginTransaction(); 
    } 

    //Delete the A 

    if(!$already_in_transaction){ 
    $pdo->commit(); 
    } 
} 
function delete_B($b){ 
    global $pdo; 
    $pdo->beginTransaction(); 
    foreach($list_of_As as $a){ 
    delete_A($a); 
    } 
    $pdo->commit(); 
} 
+0

Sie könnten in Erwägung ziehen, Fremdschlüsseleinschränkungen zu verwenden (bedeutet, dass Sie von myISAM zu einer Engine wechseln müssen, die sie unterstützt). Auf diese Weise können Sie die db Kaskadierung für Sie löschen, anstatt sie zu emulieren. – prodigitalson

Antwort

2

ich die Ausnahme von ->beginTransaction() geworfen nur am Ende mit, um herauszufinden, ob ich in einer Transaktion war, und die Verwendung dieser zu entscheiden, ob in der inneren Schleife begehen.So endete delete_A() aussehen wie:

function delete_A($a){ 
    global $pdo; 
    try { 
    $pdo->beginTransaction(); 
    } catch (PDOException $e) { 
    $already_in_transaction = true; 
    } 

    //Delete the A 

    if(!$already_in_transaction){ 
    $pdo->commit(); 
    } 
} 

Und delete_B() Werke ohne Modifikation.

+0

Was passiert, wenn dies von einer anderen Routine aufgerufen wird, die die Transaktion gestartet hat und sich für ein Rollback entscheidet? Ihr Löschen wird rückgängig gemacht. –

1

Eine Möglichkeit, um sich umzuziehen ist Ihre eigene PDOConnect Klasse zu erstellen, die eine $hasTransaction Variable . Dann kontrollierst du das einfach. Ein Beispiel finden Sie in den Kommentaren der BeginTransaction-Funktion auf php.net hier http://www.php.net/manual/en/pdo.begintransaction.php#81022

Das wäre meine Präferenz. Zugegeben, dieses Beispiel muss angepasst und angepasst werden, aber es sollte eine gute Grundlage sein, um damit anzufangen.

Seitennotiz Denken Sie daran, Ihre Tabelle sollte INNODB sein, damit Transaktionen funktionieren. Und da Sie in INNODB sein müssen, damit Transaktionen funktionieren, sollten Sie den Rat von Prodigitalson befolgen und Fremdschlüsseleinschränkungen verwenden.

7

PDO::ATTR_AUTOCOMMIT ist kein Indikatorattribut, es ist ein Steuerelementattribut. Es steuert, ob SQL-Anweisungen implizit festgeschrieben werden, wenn sie abgeschlossen sind.

Sie können auch anrufen PDO::inTransaction() die 0 zurückgibt, wenn Sie keine Transaktion ausgeführt haben, und 1, wenn Sie eine Transaktion ausstehen, die begangen werden muss oder zurückgerollt. Diese Funktion ist jedoch nicht dokumentiert, daher ist es schwer zu sagen, ob es sicher ist, davon abhängig zu sein, dass sie in allen zukünftigen Versionen von PDO vorhanden ist.

Ich empfehle, dass PHP-Entwickler nicht versuchen, Transaktionen innerhalb des Funktions- oder Klassenbereichs zu verwalten. Sie sollten Transaktionen auf der obersten Ebene der Anwendung verwalten.

Siehe auch:

+0

Danke für die Links, die mich zu der Lösung geführt haben, die ich am Ende benutzt habe. –

+2

inTransaction() ist jetzt dokumentiert. http://php.net/manual/de/pdo.intransaction.php – morbidCode

+0

@morbidCode, danke für das Update! –

Verwandte Themen