Start · Sprachen · PHP · Referenz · oci_set_call_timeout

oci_set_call_timeout

Funktion

Setzt ein Timeout in Millisekunden für einzelne Datenbankaufrufe über eine OCI8-Verbindung, um hängende Abfragen zu unterbrechen.

seit PHP 8.0.0 Kategorie: db

Signatur

oci_set_call_timeout(resource $connection, int $time_out): bool

Beschreibung

oci_set_call_timeout() legt ein Zeitlimit (in Millisekunden) für jeden einzelnen Datenbankaufruf fest, der über die angegebene OCI8-Verbindung ausgeführt wird. Überschreitet ein Aufruf dieses Limit, wird er abgebrochen und ein Fehler zurückgegeben. Dadurch lassen sich hängende oder langsam reagierende Datenbankanfragen kontrolliert beenden.

Das Timeout gilt pro Roundtrip zur Datenbank, nicht für die gesamte Verbindungsdauer. Das bedeutet, dass eine Transaktion mit mehreren Aufrufen mehrere Timeouts auslösen kann, wenn jeder einzelne Aufruf das Limit überschreitet.

Diese Funktion ist besonders nützlich in Webanwendungen, bei denen unkontrolliert lange laufende SQL-Abfragen zu Ressourcenengpässen führen können. Sie ergänzt serverseitige Oracle-Mechanismen wie Resource Manager und sollte in Kombination mit angemessener Fehlerbehandlung eingesetzt werden.

Die Funktion setzt intern das OCI_ATTR_CALL_TIMEOUT-Attribut der Oracle Call Interface (OCI). Sie erfordert Oracle Client-Bibliotheken ab Version 18c oder höher. Bei älteren Client-Versionen schlägt der Aufruf fehl.

Parameter

Name Typ Default Beschreibung
$connection Pflicht resource Eine gültige OCI8-Verbindungsressource, wie sie von oci_connect(), oci_pconnect() oder oci_new_connect() zurückgegeben wird.
$time_out Pflicht int Maximale Dauer in Millisekunden, die ein einzelner Datenbankaufruf dauern darf. Ein Wert von 0 deaktiviert das Timeout (kein Limit).

Rückgabewert

Typ
bool
Beschreibung
Gibt true bei Erfolg zurück. Im Fehlerfall (z. B. bei zu alter Oracle-Client-Bibliothek oder ungültiger Verbindungsressource) wird false zurückgegeben.

Beispiele

Timeout für eine einzelne Datenbankverbindung setzen

<?php
$conn = oci_connect('hr', 'geheimespasswort', 'localhost/XE');

if (!$conn) {
    $e = oci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

// Timeout auf 5000 Millisekunden (5 Sekunden) setzen
$result = oci_set_call_timeout($conn, 5000);

if (!$result) {
    echo "Timeout konnte nicht gesetzt werden (Oracle Client >= 18c erforderlich).";
} else {
    echo "Timeout erfolgreich auf 5 Sekunden gesetzt.\n";
}

$stid = oci_parse($conn, 'SELECT * FROM employees');

if (!oci_execute($stid)) {
    $e = oci_error($stid);
    // ORA-03136 deutet auf ein überschrittenes Timeout hin
    echo "Fehler: " . htmlentities($e['message']) . "\n";
} else {
    while ($row = oci_fetch_array($stid, OCI_ASSOC)) {
        echo $row['EMPLOYEE_ID'] . " - " . $row['LAST_NAME'] . "\n";
    }
}

oci_free_statement($stid);
oci_close($conn);
Timeout erfolgreich auf 5 Sekunden gesetzt. 100 - King 101 - Kochhar ...

Timeout deaktivieren (kein Limit)

<?php
$conn = oci_connect('hr', 'geheimespasswort', 'localhost/XE');

if (!$conn) {
    $e = oci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

// Zuerst ein kurzes Timeout setzen
oci_set_call_timeout($conn, 2000); // 2 Sekunden

// Für eine bestimmte, lang laufende Abfrage das Timeout deaktivieren
oci_set_call_timeout($conn, 0); // Kein Timeout

$stid = oci_parse($conn, 'SELECT COUNT(*) AS cnt FROM very_large_table');
oci_execute($stid);
$row = oci_fetch_array($stid, OCI_ASSOC);
echo "Anzahl Datensätze: " . $row['CNT'] . "\n";

oci_free_statement($stid);
oci_close($conn);
Anzahl Datensätze: 1500000

// Wichtig · Fallstricke

Oracle Client-Version: oci_set_call_timeout() erfordert Oracle Client-Bibliotheken ab Version 18c. Bei älteren Versionen gibt die Funktion false zurück. Die Oracle-Serverversion spielt dabei keine Rolle — entscheidend ist die Client-Bibliothek.

Fehlercode: Wird ein Timeout überschritten, gibt Oracle den Fehlercode ORA-03136 zurück. Dieser sollte in der Fehlerbehandlung explizit abgefangen werden, um zwischen einem Timeout und anderen Datenbankfehlern unterscheiden zu können.

Gültigkeitsbereich: Das Timeout gilt pro Datenbankaufruf (Roundtrip), nicht für die gesamte Verbindung oder Transaktion. Lange Transaktionen mit mehreren einzelnen Aufrufen werden durch das Timeout jeweils pro Aufruf begrenzt.

Persistente Verbindungen: Bei persistenten Verbindungen (oci_pconnect()) sollte das Timeout bei jeder Nutzung neu gesetzt werden, da persistente Verbindungen zwischen Requests wiederverwendet werden und ein zuvor gesetztes Timeout möglicherweise noch aktiv ist.