Start · Sprachen · PHP · Referenz · MongoDB\Driver\Session

MongoDB\Driver\Session

Klasse

Repräsentiert eine Client-Sitzung für Transaktionen und kausale Konsistenz im MongoDB-Treiber.

seit PHP 1.4.0 Kategorie: db

Signatur

class MongoDB\Driver\Session

Beschreibung

Eine MongoDB\Driver\Session-Instanz kapselt eine logische Sitzung, die vom MongoDB-Server verwaltet wird. Sitzungen ermöglichen kausale Konsistenz (Lese-nach-Schreibe-Garantien) und sind die Grundlage für Multi-Dokument-Transaktionen, die ab MongoDB 4.0 (Replica Sets) und 4.2 (Sharded Clusters) unterstützt werden.

Instanzen werden nicht direkt über new Session() erzeugt, sondern ausschließlich über MongoDB\Driver\Manager::startSession(). Die Sitzung muss anschließend den gewünschten Lese-/Schreib-Operationen übergeben werden (z. B. als Option in MongoDB\Driver\Query oder MongoDB\Driver\BulkWrite).

Für Transaktionen wird die Sitzung mit startTransaction() gestartet, Operationen werden innerhalb der Transaktion ausgeführt, und am Ende wird entweder commitTransaction() oder abortTransaction() aufgerufen. Es empfiehlt sich, Transaktionen in einer Retry-Schleife zu verpacken, da vorübergehende Fehler (z. B. TransientTransactionError) durch Wiederholung behoben werden können.

Nach der Verwendung sollte die Sitzung mit endSession() explizit beendet werden, um die serverseitige Ressource freizugeben. Andernfalls wird sie beim Destruktor automatisch geschlossen.

Beispiele

Einfache Multi-Dokument-Transaktion

<?php
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');

$session = $manager->startSession();

try {
    $session->startTransaction([
        'readConcern'  => new MongoDB\Driver\ReadConcern('snapshot'),
        'writeConcern' => new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY),
    ]);

    // Schreiboperation innerhalb der Transaktion
    $bulk = new MongoDB\Driver\BulkWrite();
    $bulk->insert(['name' => 'Alice', 'balance' => 500]);
    $manager->executeBulkWrite('testdb.accounts', $bulk, ['session' => $session]);

    $bulk2 = new MongoDB\Driver\BulkWrite();
    $bulk2->insert(['name' => 'Bob', 'balance' => 300]);
    $manager->executeBulkWrite('testdb.accounts', $bulk2, ['session' => $session]);

    $session->commitTransaction();
    echo "Transaktion erfolgreich abgeschlossen.\n";
} catch (MongoDB\Driver\Exception\CommandException $e) {
    $session->abortTransaction();
    echo 'Transaktion abgebrochen: ' . $e->getMessage() . "\n";
} finally {
    $session->endSession();
}
Transaktion erfolgreich abgeschlossen.

Retry-Schleife für transiente Fehler

<?php
function runTransactionWithRetry(MongoDB\Driver\Manager $manager, callable $callback): void
{
    $session = $manager->startSession();
    try {
        while (true) {
            try {
                $session->startTransaction();
                $callback($session, $manager);
                $session->commitTransaction();
                break; // Erfolgreich
            } catch (MongoDB\Driver\Exception\CommandException $e) {
                $labels = $e->getErrorLabels();
                if (in_array('TransientTransactionError', $labels, true)) {
                    // Vorübergehender Fehler — erneut versuchen
                    continue;
                }
                $session->abortTransaction();
                throw $e;
            }
        }
    } finally {
        $session->endSession();
    }
}

$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');

runTransactionWithRetry($manager, function (MongoDB\Driver\Session $session, MongoDB\Driver\Manager $mgr) {
    $bulk = new MongoDB\Driver\BulkWrite();
    $bulk->updateOne(
        ['name' => 'Alice'],
        ['$inc' => ['balance' => -100]]
    );
    $mgr->executeBulkWrite('testdb.accounts', $bulk, ['session' => $session]);

    $bulk2 = new MongoDB\Driver\BulkWrite();
    $bulk2->updateOne(
        ['name' => 'Bob'],
        ['$inc' => ['balance' => 100]]
    );
    $mgr->executeBulkWrite('testdb.accounts', $bulk2, ['session' => $session]);

    echo "Überweisung durchgeführt.\n";
});
Überweisung durchgeführt.

// Wichtig · Fallstricke

Kausale Konsistenz: Wenn dieselbe Session-Instanz für aufeinanderfolgende Lese- und Schreiboperationen genutzt wird, garantiert MongoDB, dass spätere Lese-Operationen immer die vorherigen Schreibvorgänge sehen — auch in verteilten Replica Sets.

Transaktionsgrenzen: Innerhalb einer Transaktion sind DDL-Operationen (z. B. Collection-Erstellung) und bestimmte Befehle nicht erlaubt. Transaktionen sollten möglichst kurz gehalten werden, da sie Sperren auf dem Server halten.

Ressourcen freigeben: endSession() sollte immer in einem finally-Block aufgerufen werden, damit serverseitige Sitzungsressourcen zeitnah freigegeben werden und der Sitzungspool des Servers nicht erschöpft wird.

Nicht thread-sicher: Eine Session-Instanz darf nicht von mehreren PHP-Threads oder -Prozessen gleichzeitig genutzt werden.