Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Diagnostizieren und beheben Sie häufige Probleme, wenn Sie die Microsoft-Treiber für PHP für SQL Server verwenden, um eine Verbindung mit SQL Server, Azure SQL-Datenbank, Azure SQL Managed Instance und SQL-Datenbank in Microsoft Fabric herzustellen.
Allgemeine Fehler- und Warnmuster finden Sie unter Handhabung von Fehlern und Warnungen. Zur Diagnoseerfassung auf der Treiberseite siehe Protokollierungsaktivität.
Installationsprobleme
Erweiterung nicht geladen
Symptome:
-
phpinfo()listet keinen Abschnitt fürsqlsrvoderpdo_sqlsrvauf. -
PDOException: could not find driverbeim Erstellen einesPDOmit demsqlsrv:-DSN. -
Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect().
Mögliche Ursachen und Lösungen:
-
Die Erweiterung ist in php.ini nicht aktiviert. Vergewissern Sie sich, dass sowohl
extension=sqlsrvals auchextension=pdo_sqlsrvnicht auskommentiert sind. Unter Windows verwenden Sie den vollständigen Dateinamen (extension=php_sqlsrv_84_ts_x64.dll). Details finden Sie unter Laden der Treiber. -
Falscher Gewindesicherungsbau. Die Treiber-Binärform muss mit der Thread-Sicherheit deines PHP-Builds übereinstimmen (
tsfür threadsicher,ntsfür nicht-threadsicher). Führen Siephp -i | grep "Thread Safety"zum Prüfen aus. Laden Sie die passende Binärdatei von der Download-Seite herunter. -
Microsoft ODBC-Treiber fehlt. Die PHP-Treiber umschließen den Microsoft ODBC Driver für SQL Server. Unter Linux und macOS installiere
msodbcsql18(odermsodbcsql17) mit deinem Paketmanager, bevor du die Erweiterungen lädst. Installiere unter Windows den ODBC-Treiber von der Download-Seite.
Überprüfen Sie eine erfolgreiche Installation:
php -m | grep -i sqlsrv
Du solltest sowohl pdo_sqlsrv als auch sqlsrv in der Ausgabe sehen.
PECL-Installation schlägt auf Linux oder macOS fehl
Symptome:
error: ‘SQL_HANDLE_DBC’ undeclared (first use in this function)
fatal error: 'sql.h' file not found
Korrektur:
Installieren Sie die ODBC-Entwicklungs-Header-Dateien, bevor Sie pecl install ausführen:
-
Ubuntu und Debian:
sudo apt-get install unixodbc-dev -
Red Hat, Fedora und CentOS:
sudo dnf install unixODBC-devel -
Alpine:
apk add unixodbc-dev -
macOS:
brew install unixodbc
Versuchen Sie es dann noch einmal:
sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv
Wenn pecl nach der Installation der Header weiterhin fehlschlägt, ist die Build-Toolchain möglicherweise unvollständig. Installiere phpize, re2c, und einen C++-Compiler (build-essential auf Debian und Ubuntu, gcc-c++ make auf Red Hat und Fedora, build-base auf Alpine).
Für den vollständigen Installationspfad siehe Installationsanleitung für Linux und macOS.
Mehrere PHP-Versionen installiert
Symptome:
phpinfo() auf deinem Webserver wird eine PHP-Version angezeigt, aber php -v in der Kommandozeile eine andere, und der Treiber wird nur in einer davon geladen.
Korrektur:
Jede PHP-Version hat ihr eigenes php.ini- und ext-Verzeichnis. Finde die richtige Konfigurationsdatei php --ini aus der Umgebung, der der Treiber fehlt, und füge dort die extension= Zeilen hinzu. Neustarte den Webserver (Apache, Nginx + PHP-FPM oder IIS) nach jeder php.ini Änderung.
Verbindungsprobleme
Keine Verbindung zum Server möglich
Symptome:
SQLSTATE[08001]: [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider: A connection attempt failed
SQLSTATE[HYT00]: [Microsoft][ODBC Driver 18 for SQL Server]Login timeout expired
Mögliche Ursachen und Lösungen:
Der Server ist nicht erreichbar. Überprüfen Sie, ob Servername und Port korrekt sind. Vom PHP-Host aus testen Sie die rohe TCP-Konnektivität.
# Linux and macOS nc -vz <server>.database.windows.net 1433 # Windows PowerShell Test-NetConnection -ComputerName <server>.database.windows.net -Port 1433Firewall blockiert ausgehenden Port 1433. Unternehmensfirewalls und Cloud-NSGs blockieren häufig den ausgehenden Port 1433. Füge eine Ausnahme hinzu oder erlaube die Azure SQL-Datenbank-IP-Bereiche für deine Region.
Azure SQL Server Firewall. Füge die öffentliche IP deines Kunden zu den Server-Firewall-Regeln im Azure-Portal hinzu.
Benannte Instanz. Für eine benannte Instanz überprüfen Sie, ob der SQL Server Browser-Dienst auf dem Server läuft und dass UDP 1434 offen ist. Oder verbinden Sie sich über den Port statt über den Instanznamen.
Fehler bei der Anmeldung
Symptome:
SQLSTATE[28000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Login failed for user '<user_id>'.
Mögliche Ursachen und Lösungen:
- SQL-Authentifizierungsmodus deaktiviert. Lokale SQL Server-Instanzen verwenden standardmäßig nur Windows-Authentifizierung. Aktivieren Sie die Authentifizierung im gemischten Modus im SQL Server Management Studio unter Server Properties>Security und starten Sie dann den SQL Server-Dienst neu.
-
Azure SQL credentials format. Azure SQL benötigt den vollständig qualifizierten Benutzernamen (
user@servername) beim Verbinden mit Tools, die es nicht automatisch anhängen. - Benutzer nicht der Datenbank zugeordnet. Überprüfen Sie, dass der Login eine Benutzerzuordnung in der Zieldatenbank enthält und der Benutzer die erforderlichen Berechtigungen hat.
-
Bevorzuge Microsoft Entra ID. Für Azure SQL, Azure SQL Managed Instance und SQL-Datenbank in Fabric verwenden Sie Microsoft Entra-Authentifizierung (
Authentication=ActiveDirectoryMsi,Authentication=ActiveDirectoryServicePrincipal, oder ein Zugriffstoken) anstelle von SQL-Logins. Siehe Verbinden mit der Microsoft Entra-Authentifizierung.
Ungültiger Wert angegeben für das Verbindungszeichenfolge-Attribut 'Authentication'
Symptome:
SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Invalid value specified for connection string attribute 'Authentication'
Ursache:
Der ODBC-Treiber meldet den Fehler, aber das eigentliche Problem ist, an welchen Treiber PDO_SQLSRV gebunden ist. Wenn das DSN kein Driver= Schlüsselwort enthält und der Host sowohl ODBC 17 als auch ODBC 18 installiert hat, kann PDO_SQLSRV auf die ältere Version binden. Ältere ODBC 17.x-Builds kennen keine neueren Authentication Werte wie ActiveDirectoryServicePrincipal oder ActiveDirectoryDefault, und benötigen sogar ActiveDirectoryMsi ODBC 17.3.1.1 oder eine neuere Version.
Korrektur:
Treiber im DSN anheften:
<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
"Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
Die in Klammern gesetzte Form ({ODBC Driver 18 for SQL Server}) entfällt den Leerzeichen im Fahrernamen. Die Fehlermeldung selbst nennt immer den gemeldeten Treiber, sodass das Präfix [Microsoft][ODBC Driver 17 for SQL Server] im Fehler der schnellste Weg ist, die falsche Treiberbindung zu bestätigen.
Das ungültige Schlüsselwort 'UID' wurde im DSN-String angegeben
Symptome:
SQLSTATE[IMSSP]: An invalid keyword 'UID' was specified in the DSN string.
Ursache:
PDO_SQLSRV erzwingt eine Liste zulässiger DSN-Schlüsselwörter und akzeptiert UID oder PWD in der DSN nicht. PDO reserviert das zweite und dritte Konstruktorargument dafür, und PDO_SQLSRV übersetzt diese intern in ODBC UID/PWD.
Korrektur:
Übertragen Sie den Benutzernamen (und das Passwort für SQL-Authentifizierung) in den PDO-Konstruktor:
<?php
// SQL authentication.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;Encrypt=true";
$conn = new PDO($dsn, $user, $password);
// User-assigned managed identity. Pass the identity's client ID as $username.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
"Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, $clientId, null);
Der prozedurale SQLSRV-Treiber hingegen akzeptiert UID und PWD im Array der Verbindungsoptionen, das an sqlsrv_connect() übergeben wird.
PDO_SQLSRV ignoriert AccessToken im Options-Array stillschweigend
Symptom:
Du verfügst über ein Microsoft Entra-Zugriffstoken (zum Beispiel von az account get-access-token --resource https://database.windows.net/, ManagedIdentityCredential oder ClientSecretCredential) und übergibst es als ['AccessToken' => $token] im vierten Konstruktorargument an PDO_SQLSRV. Der Verbindungsversuch scheitert mit einem verwirrenden Fehler wie Windows logins are not supported in this version of SQL Server oder Login failed for user '', als ob keine Zugangsdaten angegeben worden wären.
Ursache:
Das vierte Konstruktorargument von PDO ist für treiberspezifische Attributkonstanten (ganzzahlige Schlüssel wie PDO::ATTR_ERRMODE) reserviert. PDO verwirft stillschweigend Einträge mit Zeichenfolgenschlüsseln wie AccessToken, sodass PDO_SQLSRV den Token nie zu Gesicht bekommt. Die Verbindung fällt dann auf Windows Integrated Authentication zurück, die der Server ablehnt.
Korrektur:
Verschieben Sie AccessToken in die DSN-Zeichenfolge. Reserviere das Options-Array für PDO::ATTR_* Konstanten.
<?php
$server = '<server>.database.windows.net';
$token = getenv('SQL_ACCESS_TOKEN'); // raw JWT, no "Bearer " prefix
$dsn = "sqlsrv:Server=$server;Database=<database>;Encrypt=true;AccessToken=$token";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Für weitere Beispiele Microsoft Entra Authentifizierung, einschließlich des DSN-Formulars für PDO_SQLSRV, siehe Verbinden mit Microsoft Entra Authentifizierung.
Für prozedurales SQLSRV gehört AccessToken in das connection-info-Array, das an sqlsrv_connect() übergeben wird, welches das unformatierte JWT für Sie in SQL_COPT_SS_ACCESS_TOKEN umschließt:
<?php
$server = '<server>.database.windows.net';
$token = getenv('SQL_ACCESS_TOKEN'); // raw JWT, no "Bearer " prefix
$connectionInfo = [
'Database' => '<database>',
'AccessToken' => $token,
'Encrypt' => true,
'TrustServerCertificate' => false,
'Driver' => '{ODBC Driver 18 for SQL Server}',
];
$conn = sqlsrv_connect($server, $connectionInfo);
if ($conn === false) {
print_r(sqlsrv_errors());
exit(1);
}
TLS-Zertifikatsfehler
Symptome:
SQLSTATE[08001]: SSL Provider: The certificate chain was issued by an authority that is not trusted
SQLSTATE[08001]: SSL Provider: The target principal name is incorrect
Lösungen:
Bevorzuge ein vertrauenswürdiges Zertifikat. Verwenden Sie TrustServerCertificate=true es nur für lokale Entwicklung gegen einen Server, den Sie steuern.
Für die Entwicklung mit einem selbstsignierten Zertifikat:
<?php
$server = 'localhost';
$database = '<database>';
$user = '<user_id>';
$password = '<password>';
$dsn = "sqlsrv:Server=$server;Database=$database;Encrypt=true;TrustServerCertificate=true";
$conn = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Caution
TrustServerCertificate=true Deaktivieren Sie die Validierung von Serverzertifikaten. Nimm dieses Setting niemals in Produktion, Inszenierung oder gemeinsame Umgebungen mit.
Für einen Produktions-Hostnamen, der nicht mit dem Common Name des Zertifikats übereinstimmt (zum Beispiel, wenn die Verbindung über einen Listener hergestellt wird), geben Sie den tatsächlichen Zertifikatssubjektnamen an:
<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;Encrypt=true;HostNameInCertificate=*.database.windows.net;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Verbindungstimeout
Symptome:
SQLSTATE[HYT00]: Login timeout expired
Mögliche Ursachen und Lösungen:
-
LoginTimeoutnicht festgelegt oder zu niedrig für ein Cold Failover festgelegt. Geben Sie beim Herstellen der Verbindung mit Azure SQL im DSN einen expliziten WertLoginTimeout(in Sekunden) an. Failover von Failovergruppen und Kaltstartdatenbanken können länger dauern, als ein kurzes clientseitiges Timeout zulässt. Siehe Verbindungsoptionen für die Optionsreferenz. -
Budget für die Wiederverbindung im Leerlauf abgeschnitten. Wenn Sie
ConnectRetryCountundConnectRetryIntervalfestlegen, stellen Sie sicher, dassLoginTimeout >= ConnectRetryCount * ConnectRetryInterval. Andernfalls beendet die Login-Timeout die Wiederverbindungsschleife vorzeitig. Siehe Inaktiv-Verbindungs-Resilienz.
<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=<server>.database.windows.net;Database=<database>;" .
"Encrypt=true;LoginTimeout=90;ConnectRetryCount=5;ConnectRetryInterval=15;" .
"Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Abfrageausführungsprobleme
Stille Fehler bei PDO
Symptom:
Ein PDO::exec()- oder PDOStatement::execute()-Aufruf gibt false zurück, löst aber keine Ausnahme aus.
Korrektur:
Bei PHP 8.0 und höheren Versionen ist der Standard-PDO-Fehlermodus PDO::ERRMODE_EXCEPTION. Wenn ein Aufruf false zurückgibt, ohne eine Ausnahme auszulösen, hat die Anwendung den Modus in PDO::ERRMODE_SILENT oder PDO::ERRMODE_WARNING geändert. Setze es zurück in den Ausnahmemodus, damit Fehler Ausnahmen auslösen:
<?php
$conn = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Wenn du den Modus global nicht ändern kannst, überprüfe $conn->errorInfo() (oder $stmt->errorInfo()) nach jedem Anruf. Das Array enthält [SQLSTATE, driver code, driver message].
Ungültiger Objektname
Symptome:
SQLSTATE[42S02]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Invalid object name 'Products'.
Mögliche Ursachen und Lösungen:
Falscher Datenbankkontext. Überprüfen Sie dies mit einer kurzen Frage:
<?php $stmt = $conn->query("SELECT DB_NAME()"); echo $stmt->fetchColumn();Fehlende Schema-Qualifikation. Verwenden Sie vollständig qualifizierte Namen, um nicht auf das Standardschema des Anrufers zu vertrauen:
SELECT * FROM dbo.Products;Unterscheidung nach Groß-/Kleinschreibung. Datenbanken, die mit einer fallabhängigen Sortierung erstellt werden, behandeln
productsundProductsals verschiedene Objekte. Achten Sie auf die genaue Groß-/Kleinschreibung in der Tabellendefinition.
Falsche Anzahl von Parametern
Symptome:
SQLSTATE[HY093]: Invalid parameter number
SQLSTATE[07002]: COUNT field incorrect or syntax error
Korrektur:
Für PDO_SQLSRV muss die Anzahl der ?-Platzhalter mit der Anzahl der Werte übereinstimmen, die du an execute() übergibst, und jedes ? bindet genau einen skalaren Wert (kein Array). Für benannte Parameter muss jeder :name im SQL im Array erscheinen und umgekehrt.
<?php
$stmt = $conn->prepare(
"SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?"
);
$stmt->execute([1, 50.0]);
foreach ($stmt as $row) {
// ...
}
Für SQLSRV übergeben Sie das Parameterarray an sqlsrv_query() oder sqlsrv_prepare():
<?php
$stmt = sqlsrv_query(
$conn,
"SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?",
[1, 50.0]
);
if ($stmt === false) {
die(print_r(sqlsrv_errors(), true));
}
Für eine umfassendere Einführung in die Parameterbindung siehe Parametrisierte Abfragen ausführen.
Emulierte PDO-Prepares maskieren Fehler
Symptome:
Eine Anweisung läuft erfolgreich auf einer Verbindung, wirft aber einen Syntaxfehler bei einer anderen Verbindung, die denselben Abfragetext verwendet.
Ursache:
PDO_SQLSRV unterstützt sowohl emulierte als auch native vorbereitete Anweisungen. Emulierte Prepares (PDO::ATTR_EMULATE_PREPARES = true) interpolieren Parameter clientseitig. Native Prepares (false) senden die Abfrage und die Parameter separat an den Server. Das Verhalten unterscheidet sich für TOP (?), Tabellenwertparameter und einige Randfälle bei der Typkoersion.
Korrektur:
Bevorzugen Sie native Prepares in der Produktion. Legen Sie PDO::ATTR_EMULATE_PREPARES => false beim Verbindungsaufbau fest, damit das Verhalten in allen Umgebungen konsistent ist:
<?php
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
Einzelheiten dazu, wann die einzelnen Modi verwendet werden sollten, finden Sie unter PDO::prepare.
Datentypprobleme
Unicode-Zeichen erscheinen als ? oder verzerrt
Symptome:
Zeilen, die PHP schreibt, enthalten Fragezeichen oder Ersatzzeichen anstelle der ursprünglichen nicht-ASCII-Zeichen. Lesevorgänge geben verstümmelten Text zurück.
Mögliche Ursachen und Lösungen:
Der Spaltentyp ist VARCHAR, nicht NVARCHAR. Varchar-Spalten verwenden eine Codepage, nicht Unicode. Verwenden Sie nvarchar für internationalisierte Texte.
Fehlt der Hinweis zur UTF-8-Codierung auf PDO_SQLSRV. Wenn deine SQL Server-Spalte nvarchar ist und deine PHP-Daten UTF-8, sag dem Treiber, er soll zwischen UTF-8 (Client) und UTF-16 (Server) konvertieren:
<?php $conn = new PDO( "sqlsrv:Server=<server>;Database=<database>;Encrypt=true", $user, $password, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, ] );SQLSRV-Treiber: Fordern Sie explizit UTF-8 an.
SQLSRV_ENC_CHARist die Standard-8-Bit-Systemcodepage, nicht UTF-8. Legen Sie für UTF-8 mit SQLSRV"CharacterSet" => "UTF-8"für die Verbindung fest, und übergeben Sie das Literal'UTF-8'beim Abrufen oder Binden anSQLSRV_PHPTYPE_STRING. Siehe Senden und abrufen von UTF-8-Daten.
Fehler bei Date-Time-Umrechnungen
Symptome:
SQLSTATE[22007]: Invalid character value for cast specification
Korrektur:
In PDO_SQLSRV binden Sie kein unverarbeitetes DateTime-Objekt. PDO stringifiziert gebundene Werte vor der Bindung, und PHP DateTime hat keine Methode __toString() , daher execute([new DateTime(...)]) erhöht Object of class DateTime could not be converted to string. Formatiere zuerst den Wert oder übergebe eine ISO-8601-Zeichenkette (YYYY-MM-DD HH:MM:SS[.fff]), nicht eine lokalformatierte Zeichenkette.
<?php
$stmt = $conn->prepare("INSERT INTO dbo.Events (EventDate) VALUES (?)");
$stmt->execute([(new DateTime("2026-03-15 10:00:00"))->format("Y-m-d H:i:s.u")]);
Um Datetime-Spalten als DateTime Objekte statt Strings auf PDO_SQLSRV abzurufen, setzen Sie das Statement-Attribut:
<?php
$stmt = $conn->prepare("SELECT EventDate FROM dbo.Events");
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt->execute();
Details finden Sie unter Datetime-Objekte abrufen (PDO_SQLSRV).
Dezimalformatierungsprobleme
Symptome:
Werte zwischen -1 und 1 fehlen eine führende Null, oder Geld- und Smallmoney-Werte zeigen eine unerwartete Anzahl von Dezimalstellen.
Korrektur:
PDO_SQLSRV ruft decimal- und numeric-Werte immer als Zeichenfolgen mit ihrer genauen Präzision und Skalierung ab. Setzen Sie PDO::SQLSRV_ATTR_FORMAT_DECIMALS so ein, dass eine führende Null zu Werten zwischen -1 und 1 hinzugefügt wird:
<?php
$conn->setAttribute(PDO::SQLSRV_ATTR_FORMAT_DECIMALS, true);
PDO::SQLSRV_ATTR_DECIMAL_PLACES gilt nur für Geld- und Kleingeldwerte . Legt die angezeigte Skala auf einen Bereich von 0 bis 4 fest und kann den angezeigten Wert runden. Sie beeinflusst keine Dezimalwerte oder numerischen Werte.
Einzelheiten finden Sie unter Format decimals and money (PDO_SQLSRV) oder Format decimals and money (SQLSRV).
Transaktionsprobleme
Datenänderungen werden nicht gespeichert
Symptome:
Zeilen, die du in PHP einfügst oder aktualisierst, erscheinen nicht, wenn du aus einer anderen Sitzung abfragst.
Ursache:
PDO::beginTransaction() öffnet eine explizite Transaktion, die ein explizites commit() erfordert. Wenn das PHP-Skript ohne Aufruf commit()endet, rollt PDO die Transaktion während der Verbindungsreinigung zurück.
Korrektur:
beginTransaction() immer mit commit() koppeln und try/catch verwenden, um bei einem Fehler ein Rollback durchzuführen:
<?php
try {
$conn->beginTransaction();
$conn->exec("INSERT INTO dbo.Orders (CustomerID, Total) VALUES (1, 100)");
$conn->exec("UPDATE dbo.Inventory SET Stock = Stock - 1 WHERE ProductID = 5");
$conn->commit();
} catch (PDOException $e) {
$conn->rollBack();
throw $e;
}
Verwenden Sie für SQLSRV sqlsrv_begin_transaction, sqlsrv_commit und sqlsrv_rollback.
Deadlock-Fehler
Symptome:
SQLSTATE[40001]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Transaction (Process ID 62) was deadlocked
Korrektur:
Behandle vorübergehende Deadlock-Fehler mit Retry-Logik. Umschließen Sie die gesamte Transaktion (nicht nur die fehlerhafte Anweisung), damit frühere Anweisungen in der neuen Transaktion wiederholt werden. Für ein produktionsorientiertes Wiederholungsmuster siehe das Beispiel auf der PHP-Treiber-Landingpage.
Wiederkehrende Deadlocks weisen auf ein Designproblem hin. Erfassen Sie das Deadlockdiagramm, und analysieren Sie, welche Anweisungen und Sperrtypen beteiligt sind. Gängige Lösungen umfassen die Umordnung von Operationen, sodass konkurrierende Transaktionen Sperren in derselben Reihenfolge erhalten, die Verringerung des Transaktionsumfangs sowie das Hinzufügen von Indizes zur Verkürzung der Sperrdauer. Für eine vollständige Anleitung siehe Deadlocks-Leitfaden.
Probleme der Verbindungsresilienz
Eine Wiederverbindung passiert nicht
Symptome:
Eine im Leerlauf befindliche Verbindung bleibt nach einem Azure SQL-Datenbank-Failover unterbrochen, obwohl Sie ConnectRetryCount und ConnectRetryInterval festgelegt haben.
Mögliche Ursachen und Lösungen:
-
Aktiver serverseitiger Cursor. Die Resilienz von Verbindungen im Leerlauf stellt nur im Leerlauf befindliche Verbindungen wieder her. Ein offener serverseitiger Cursor oder eine ausstehende Transaktion hält die Verbindung aktiv. Geben Sie serverseitige Cursor vor dem Failover-Fenster mithilfe von
sqlsrv_free_stmt()oder$stmt = null;(PDO) frei, oder wechseln Sie zu einem clientseitigen gepufferten Cursor. Siehe Inaktiv-Verbindungs-Resilienz. -
Zustand der nicht wiederherstellbaren Sitzung. Einige Sitzungszustände können nicht wiederhergestellt werden, einschließlich temporärer Tabellen, globalen und lokalen Cursors, Transaktionskontext, Anwendungssperren,
EXECUTE AS/REVERTOLE-Automatisierungshandles, vorbereiteten XML-Handles und Trace-Flags. Jeder dieser Sitzungszustände verhindert eine automatische Wiederverbindung. -
LoginTimeoutzu klein. WennConnectRetryCount * ConnectRetryInterval > LoginTimeout, beendet der Treiber die Wiederholungsversuche, sobaldLoginTimeouterreicht ist. Erhöhen SieLoginTimeout, um das gesamte Wiederholungsbudget abzudecken.
Leistungsprobleme
Informationen zur Diagnose und Behebung von langsamen Abfragen, Kaltstarts, großen Resultsets und Masseneinfügungen finden Sie unter Leistungsoptimierung.
Treiberdiagnostik aktivieren
Wenn Anrufe auf Anwendungsebene error_log() nicht genügend Informationen liefern, aktivieren Sie die Fahrerseiten-Protokollierung. Es meldet jeden ODBC-Anruf, den der Fahrer tätigt.
PDO_SQLSRV
Setze pdo_sqlsrv.log_severity in php.ini und starte den Webserver neu. Diese Einstellung ist nur bei der Initialisierung lesbar:
[pdo_sqlsrv]
pdo_sqlsrv.log_severity = 1
Die Werte sind 0 (ausgeschaltet, der Standard), -1 (Fehler, Warnungen und Hinweise), 1 (Fehler), (Warnungen 2 ) und 4 (Hinweise).
SQLSRV
Aktiviere das Logging zur Laufzeit mit sqlsrv_configure():
<?php
sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_CONN | SQLSRV_LOG_SYSTEM_STMT);
sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ERROR | SQLSRV_LOG_SEVERITY_WARNING);
Protokolleinträge werden in die Datei geschrieben, die von error_log in php.ini konfiguriert wurde. Für die vollständige Liste der Teilsysteme und Schweregrade siehe Aktivitätenprotokoll.
Container- und CI-Probleme
Fehlende Systembibliotheken unter Linux
Symptome:
error while loading shared libraries: libodbc.so.2: cannot open shared object file
error while loading shared libraries: libssl.so.1.1: cannot open shared object file
Korrektur:
Installiere die Laufzeitabhängigkeiten, bevor du den PHP-Treiber installierst:
| Verteilung | Installationsbefehl |
|---|---|
| Ubuntu und Debian | sudo apt-get install unixodbc libgssapi-krb5-2 |
| Red Hat und Fedora | sudo dnf install unixODBC krb5-libs |
| Alpine | apk add unixodbc gcompat |
Installieren Sie dann msodbcsql18 aus dem Microsoft-Paket-Repository. Für distribution-spezifische Paket-Repositories und Versionen siehe die ODBC-Treiberinstallationsanleitung.
Das Erstellen von Docker-Images ist erfolgreich, aber Verbindungen schlagen zur Laufzeit fehl
Symptome:
Das Image wird erstellt und PHP startet, wirft PDO::__construct() aber einen ODBC-Treiber-nicht-gefunden-Fehler.
Korrektur:
Überprüfen Sie, ob der ODBC-Treiber im Laufzeit-Image installiert ist, nicht nur in der Build-Phase. Installieren Sie msodbcsql18 und unixodbc-dev in derselben Phase, die in die Produktion überführt wird. Bei einem mehrstufigen Bau installieren Sie sie in der Endstufe. Eine einstufige Debian-basierte Installation sieht so aus:
# Pin to a specific PHP minor version in production, for example php:8.4.11-cli.
FROM php:8.4-cli
RUN apt-get update && apt-get install -y --no-install-recommends \
curl gnupg2 apt-transport-https ca-certificates \
&& curl -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /usr/share/keyrings/microsoft.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update \
&& ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 unixodbc-dev \
# $PHPIZE_DEPS ships in the official php image and includes gcc, make, autoconf, and re2c.
&& apt-get install -y --no-install-recommends $PHPIZE_DEPS \
&& pecl install sqlsrv pdo_sqlsrv \
&& docker-php-ext-enable sqlsrv pdo_sqlsrv \
&& apt-get purge -y --auto-remove $PHPIZE_DEPS \
&& rm -rf /var/lib/apt/lists/*