Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Mendiagnosis dan menyelesaikan masalah umum saat Anda menggunakan Microsoft Drivers for PHP for SQL Server untuk terhubung ke SQL Server, Azure SQL Database, Azure SQL Managed Instance, dan database SQL di Microsoft Fabric.
Untuk pola penanganan kesalahan dan peringatan umum, lihat Penanganan kesalahan dan peringatan. Untuk pengambilan data diagnostik sisi driver, lihat Aktivitas logging.
Masalah instalasi
Ekstensi tidak dimuat
Gejala:
-
phpinfo()tidak mencantumkan bagiansqlsrvataupdo_sqlsrv. -
PDOException: could not find driversaat membuatPDOdengan DSNsqlsrv:. -
Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect().
Kemungkinan penyebab dan solusi:
-
Ekstensi tidak diaktifkan di php.ini. Pastikan bahwa baik
extension=sqlsrvmaupunextension=pdo_sqlsrvtidak diberi komentar. Di Windows, gunakan nama file lengkap (extension=php_sqlsrv_84_ts_x64.dll). Untuk detail lebih lanjut, lihat Memuat driver. -
Build dengan keamanan thread yang salah. Biner driver harus sesuai dengan keamanan thread build PHP Anda (
tsuntuk thread-safe,ntsuntuk non-thread-safe). Jalankanphp -i | grep "Thread Safety"untuk memeriksa. Unduh biner yang sesuai dari halaman unduhan. -
Driver Microsoft ODBC hilang. Driver PHP membungkus Microsoft ODBC Driver for SQL Server. Di Linux dan macOS, instal
msodbcsql18(atau)msodbcsql17dengan manajer paket Anda sebelum memuat ekstensi. Di Windows, instal driver ODBC dari halaman unduhan.
Verifikasi instalasi yang berhasil:
php -m | grep -i sqlsrv
Anda seharusnya melihat keduanya pdo_sqlsrv dan sqlsrv di output.
Instalasi PECL atau PIE gagal di Linux atau macOS
Gejala:
error: ‘SQL_HANDLE_DBC’ undeclared (first use in this function)
fatal error: 'sql.h' file not found
Perbaikan:
Instal header pengembangan ODBC sebelum menginstal driver:
-
Ubuntu dan Debian:
sudo apt-get install unixodbc-dev -
Red Hat, Fedora, dan CentOS:
sudo dnf install unixODBC-devel -
Alpine:
apk add unixodbc-dev -
macOS:
brew install unixodbc
Pada Apple silicon, header saja tidak cukup. Homebrew menginstal unixODBC di /opt/homebrew, yang tidak termasuk dalam jalur pencarian kompilator default, sehingga proses build gagal dengan kesalahan yang sama meskipun berkas header sudah ada. Atur flag kompiler sebelum Anda mencoba lagi:
export CPPFLAGS="-I/opt/homebrew/opt/unixodbc/include/"
export LDFLAGS="-L/opt/homebrew/lib/"
Lalu coba ulang dengan PIE:
pie install microsoft/sqlsrv
pie install microsoft/pdo_sqlsrv
Atau dengan PECL:
sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv
Jika instalasi masih gagal setelah header dipasang, rantai alat build mungkin belum lengkap. Instal phpize, re2c, dan kompiler C++ (build-essential di Debian dan Ubuntu, gcc-c++ make di Red Hat dan Fedora, build-base di Alpine). PIE menawarkan untuk memasang alat bantu build yang belum terpasang untuk Anda di Linux dan macOS.
Untuk jalur instalasi lengkap, lihat Tutorial Instalasi untuk Linux dan macOS.
Beberapa versi PHP terpasang
Gejala:
phpinfo() di server web Anda menampilkan satu versi PHP, tetapi php -v di baris perintah menampilkan versi lain, dan driver hanya muncul di salah satu dari mereka.
Perbaikan:
Setiap versi PHP memiliki direktori php.ini dan ext masing-masing. Temukan file konfigurasi yang benar menggunakan php --ini dari dalam lingkungan yang tidak memiliki driver tersebut, lalu tambahkan baris extension= ke file itu. Restart server web (Apache, Nginx + PHP-FPM, atau IIS) setelah ada perubahan php.ini.
Masalah koneksi
Tidak dapat terhubung ke server
Gejala:
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
Kemungkinan penyebab dan solusi:
Server tidak dapat dihubungi. Periksa apakah nama server dan port sudah benar. Dari host PHP, uji konektivitas TCP mentah.
# Linux and macOS nc -vz <server>.database.windows.net 1433 # Windows PowerShell Test-NetConnection -ComputerName <server>.database.windows.net -Port 1433Firewall memblokir port 1433 keluar. Firewall korporat dan NSG cloud sering memblokir port keluar 1433. Tambahkan pengecualian, atau izinkan rentang IP Azure SQL Database untuk wilayah Anda.
Azure SQL server firewall. Tambahkan IP publik klien Anda ke aturan firewall tingkat server di portal Azure.
Instans bernama. Untuk instance bernama, pastikan layanan SQL Server Browser berjalan di server dan UDP 1434 terbuka. Atau, hubungkan berdasarkan port, bukan nama instance.
Gagal masuk
Gejala:
SQLSTATE[28000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Login failed for user '<user_id>'.
Kemungkinan penyebab dan solusi:
- Mode autentikasi SQL dinonaktifkan. Instansi SQL Server lokal secara default hanya menggunakan Autentikasi Windows. Aktifkan autentikasi mode campuran di SQL Server Management Studio di bawah properti> ServerSecurity, lalu restart layanan SQL Server.
-
Azure SQL credentials format. Azure SQL memerlukan nama pengguna lengkap (
user@servername) saat terhubung menggunakan alat yang tidak menambahkan nama pengguna tersebut secara otomatis. - Pengguna tidak dipetakan ke database. Verifikasi bahwa login memiliki pemetaan pengguna di database target dan pengguna memiliki izin yang diperlukan.
-
Lebih suka Microsoft Entra ID. Untuk Azure SQL, Azure SQL Managed Instance, dan database SQL di Fabric, gunakan autentikasi Microsoft Entra (
Authentication=ActiveDirectoryMsi,Authentication=ActiveDirectoryServicePrincipal, atau token akses) sebagai pengganti login SQL. Lihat Menyambungkan menggunakan autentikasi Microsoft Entra.
Nilai yang ditentukan tidak valid untuk atribut string koneksi 'Authentication'
Gejala:
SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Invalid value specified for connection string attribute 'Authentication'
Penyebab:
Driver ODBC melaporkan kesalahan, tetapi masalah sebenarnya adalah driver yang mana yang menjadi tempat PDO_SQLSRV terikat. Jika DSN tidak menyertakan Driver= kata kunci dan host memiliki ODBC 17 dan ODBC 18 terpasang, PDO_SQLSRV dapat mengikat ke versi lama. Build ODBC 17.x lama tidak mengetahui nilai baru Authentication seperti ActiveDirectoryServicePrincipal atau ActiveDirectoryDefault, dan bahkan ActiveDirectoryMsi membutuhkan ODBC 17.3.1.1 atau versi yang lebih baru.
Perbaikan:
Sematkan driver di DSN:
<?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]);
Formulir yang dikurung ({ODBC Driver 18 for SQL Server}) keluar dari spasi pada nama driver. Pesan kesalahan itu sendiri selalu menyebutkan driver yang melaporkannya, jadi awalan [Microsoft][ODBC Driver 17 for SQL Server] dalam kesalahan adalah cara tercepat untuk mengonfirmasi batas driver yang salah.
Kata kunci 'UID' yang tidak valid ditentukan dalam string DSN
Gejala:
SQLSTATE[IMSSP]: An invalid keyword 'UID' was specified in the DSN string.
Penyebab:
PDO_SQLSRV menegakkan daftar kata kunci DSN yang diizinkan dan tidak menerima UID atau PWD di DSN. PDO menyimpan argumen konstruktor kedua dan ketiga untuk itu, dan PDO_SQLSRV menerjemahkannya ke ODBC UID/PWD secara internal.
Perbaikan:
Pindahkan nama pengguna (dan kata sandi, untuk autentikasi SQL) ke dalam konstruktor PDO:
<?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);
Sebaliknya, driver prosedural SQLSRV menerima UID dan PWD dalam array opsi koneksi yang diteruskan ke sqlsrv_connect().
PDO_SQLSRV secara diam-diam mengabaikan AccessToken dalam larik opsi
Gejala:
Anda memiliki token akses Microsoft Entra (misalnya, dari az account get-access-token --resource https://database.windows.net/, ManagedIdentityCredential, atau ClientSecretCredential), dan Anda meneruskannya ke PDO_SQLSRV sebagai ['AccessToken' => $token] dalam argumen konstruktor keempat. Upaya koneksi gagal dengan kesalahan membingungkan seperti Windows logins are not supported in this version of SQL Server atau Login failed for user '', seolah-olah tidak ada kredensial yang diberikan.
Penyebab:
Argumen konstruktor keempat PDO dikhususkan untuk konstanta atribut spesifik driver (kunci bilangan bulat seperti PDO::ATTR_ERRMODE). PDO diam-diam menjatuhkan entri berkunci string seperti AccessToken, sehingga PDO_SQLSRV tidak pernah melihat tokennya. Koneksi kemudian kembali ke autentikasi Windows Integrasi, yang ditolak oleh server.
Perbaikan:
Pindahkan AccessToken ke dalam string DSN. Sisihkan array opsi untuk konstanta PDO::ATTR_*.
<?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,
]);
Untuk contoh autentikasi Microsoft Entra tambahan, termasuk formulir DSN untuk PDO_SQLSRV, lihat Hubungkan menggunakan autentikasi Microsoft Entra.
Untuk SQLSRV prosedural, AccessToken harus berada dalam array informasi koneksi yang diteruskan ke sqlsrv_connect(), yang membungkus JWT mentah ke dalam SQL_COPT_SS_ACCESS_TOKEN untuk Anda:
<?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);
}
Kesalahan sertifikat TLS
Gejala:
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
Solusi:
Lebih memilih sertifikat terpercaya. Gunakan TrustServerCertificate=true hanya untuk pengembangan lokal terhadap server yang Anda kendalikan.
Untuk pengembangan menggunakan sertifikat yang ditandatangani sendiri:
<?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 menonaktifkan validasi sertifikat server. Jangan pernah membawa latar itu ke dalam produksi, panggung, atau lingkungan bersama.
Untuk hostname produksi yang tidak cocok dengan sertifikat Common Name (misalnya, saat terhubung melalui listener), tentukan subjek sertifikat yang sebenarnya:
<?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,
]);
Waktu koneksi habis
Gejala:
SQLSTATE[HYT00]: Login timeout expired
Kemungkinan penyebab dan solusi:
-
LoginTimeoutTidak diatur atau diatur terlalu rendah untuk cold failover. Atur eksplisitLoginTimeout(dalam hitungan detik) di DSN saat menghubungkan ke Azure SQL. Failover pada failover-group dan database cold-start dapat memerlukan waktu lebih lama daripada yang diizinkan oleh batas waktu sisi klien yang singkat. Lihat opsi Koneksi untuk referensi opsi. -
Anggaran idle reconnect terpotong. Jika Anda mengatur
ConnectRetryCountdanConnectRetryInterval, pastikanLoginTimeout >= ConnectRetryCount * ConnectRetryInterval. Jika tidak, batas waktu login akan mengakhiri siklus penyambungan ulang lebih awal. Lihat Ketahanan koneksi saat idle.
<?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,
]);
Masalah eksekusi kueri
Kegagalan senyap dengan PDO
Gejala:
Panggilan A PDO::exec() atau PDOStatement::execute() mengembalikan false tetapi tidak melempar pengecualian.
Perbaikan:
Dengan PHP 8.0 dan versi yang lebih baru, mode kesalahan PDO default adalah PDO::ERRMODE_EXCEPTION. Jika panggilan kembali false tanpa throwing, aplikasi mengubah mode menjadi PDO::ERRMODE_SILENT atau PDO::ERRMODE_WARNING. Kembalikan ke mode pengecualian agar kegagalan melemparkan pengecualian:
<?php
$conn = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
Jika Anda tidak bisa mengubah mode secara global, centang $conn->errorInfo() (atau $stmt->errorInfo()) setelah setiap panggilan. Array ini berisi [SQLSTATE, driver code, driver message].
Nama objek tidak valid
Gejala:
SQLSTATE[42S02]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Invalid object name 'Products'.
Kemungkinan penyebab dan solusi:
Konteks database salah. Verifikasi dengan kueri cepat:
<?php $stmt = $conn->query("SELECT DB_NAME()"); echo $stmt->fetchColumn();Kualifikator skema tidak ada. Gunakan nama berkualifikasi lengkap untuk menghindari ketergantungan pada skema bawaan pemanggil:
SELECT * FROM dbo.Products;Sensitivitas kasus. Basis data yang dibuat dengan kolasi yang membedakan huruf besar dan huruf kecil menganggap
productsdanProductssebagai objek yang berbeda. Cocokkan kasus persis dalam definisi tabel.
Jumlah parameter yang salah
Gejala:
SQLSTATE[HY093]: Invalid parameter number
SQLSTATE[07002]: COUNT field incorrect or syntax error
Perbaikan:
Untuk PDO_SQLSRV, jumlah placeholder ? harus sama dengan jumlah nilai yang Anda teruskan ke execute(), dan setiap ? mengikat satu nilai skalar (bukan array). Untuk parameter bernama, setiap :name di SQL harus muncul di array dan sebaliknya.
<?php
$stmt = $conn->prepare(
"SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?"
);
$stmt->execute([1, 50.0]);
foreach ($stmt as $row) {
// ...
}
Untuk SQLSRV, kirim array parameter ke sqlsrv_query() atau 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));
}
Untuk pengantar yang lebih luas tentang pengikatan parameter, lihat Melakukan kueri yang diparameterkan.
PDO emulated menyiapkan kesalahan masker
Gejala:
Sebuah pernyataan berjalan dengan sukses pada satu koneksi tetapi melemparkan kesalahan sintaks pada koneksi lain yang menggunakan teks kueri yang sama.
Penyebab:
PDO_SQLSRV mendukung pernyataan yang diemulasikan maupun yang disiapkan secara native. Emulated prepares (PDO::ATTR_EMULATE_PREPARES = true) menginterpolasi parameter di sisi klien. Native menyiapkan (false) untuk mengirim kueri dan parameter secara terpisah ke server. Perilaku berbeda untuk TOP (?), parameter bernilai tabel, dan beberapa kasus khusus dalam koersi tipe.
Perbaikan:
Lebih memilih preparat asli dalam produksi. Atur PDO::ATTR_EMULATE_PREPARES => false pada waktu koneksi agar perilaku konsisten di berbagai lingkungan:
<?php
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
Untuk mengetahui detail tentang kapan harus menggunakan tiap mode, lihat PDO::prepare.
Masalah tipe data
Karakter Unicode muncul sebagai ? atau teks rusak
Gejala:
Baris yang ditulis PHP berisi tanda tanya atau karakter pengganti, bukan karakter non-ASCII asli. Pembacaan menghasilkan teks yang rusak.
Kemungkinan penyebab dan solusi:
Tipe kolom adalah VARCHAR, bukan NVARCHAR. kolom varchar menggunakan halaman kode, bukan Unicode. Gunakan nvarchar untuk teks internasional.
Petunjuk pengkodean UTF-8 hilang pada PDO_SQLSRV. Ketika kolom SQL Server Anda adalah nvarchar dan data PHP Anda adalah UTF-8, beri tahu driver untuk mengonversi antara UTF-8 (klien) dan UTF-16 (server):
<?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, ] );Driver SQLSRV: minta UTF-8 secara eksplisit.
SQLSRV_ENC_CHARadalah halaman kode sistem 8-bit default, bukan UTF-8. Untuk UTF-8 dengan SQLSRV, atur"CharacterSet" => "UTF-8"pada koneksi dan teruskan nilai literal'UTF-8'keSQLSRV_PHPTYPE_STRINGsaat mengambil data atau melakukan bind. Lihat Kirim dan ambil data UTF-8.
Kesalahan konversi tanggal dan waktu
Gejala:
SQLSTATE[22007]: Invalid character value for cast specification
Perbaikan:
Di PDO_SQLSRV, jangan mengikat objek mentah DateTime . PDO mengubah nilai yang diikat menjadi string sebelum pengikatan, dan DateTime milik PHP tidak memiliki metode __toString(), sehingga execute([new DateTime(...)]) memunculkan Object of class DateTime could not be converted to string. Format nilai terlebih dahulu, atau lewatkan string ISO 8601 (YYYY-MM-DD HH:MM:SS[.fff]), bukan string yang diformat lokal.
<?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")]);
Untuk mengambil kolom datetime sebagai objek DateTime bukan string pada PDO_SQLSRV, atur atribut statement:
<?php
$stmt = $conn->prepare("SELECT EventDate FROM dbo.Events");
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt->execute();
Untuk detailnya, lihat Ambil objek datetime (PDO_SQLSRV).
Masalah pemformatan desimal
Gejala:
Nilai antara -1 dan 1 tidak memiliki nol di depan, atau nilai money dan smallmoney memiliki jumlah tempat desimal yang tidak semestinya.
Perbaikan:
PDO_SQLSRV selalu mengambil nilai desimal dan numerik dalam bentuk string dengan presisi dan skala yang tepat. Atur PDO::SQLSRV_ATTR_FORMAT_DECIMALS untuk menambahkan nol di awal pada nilai antara -1 dan 1:
<?php
$conn->setAttribute(PDO::SQLSRV_ATTR_FORMAT_DECIMALS, true);
PDO::SQLSRV_ATTR_DECIMAL_PLACES Hanya berlaku untuk uang dan nilai uang kecil . Ini menetapkan skala tampilannya dari 0 hingga 4 dan mungkin membulatkan nilai yang ditampilkan. Ini tidak memengaruhi nilai desimal atau numerik .
Untuk detailnya, lihat Format desimal dan uang (PDO_SQLSRV) atau Format desimal dan uang (SQLSRV).
Masalah transaksi
Perubahan data tidak bertahan lama
Gejala:
Baris yang Anda sisipkan atau perbarui di PHP tidak muncul saat Anda melakukan query dari sesi lain.
Penyebab:
PDO::beginTransaction() membuka transaksi eksplisit yang memerlukan perintah commit() secara eksplisit. Jika skrip PHP berakhir tanpa memanggil commit(), PDO akan mengembalikan transaksi selama pembersihan koneksi.
Perbaikan:
Selalu pasangkan beginTransaction() dengan commit(), dan gunakan try/catch untuk mengembalikan perubahan jika terjadi kesalahan:
<?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;
}
Untuk SQLSRV, gunakan sqlsrv_begin_transaction, sqlsrv_commit, dan sqlsrv_rollback.
Kesalahan deadlock
Gejala:
SQLSTATE[40001]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Transaction (Process ID 62) was deadlocked
Perbaikan:
Tangani kesalahan deadlock sementara dengan logika coba lagi. Bungkus seluruh transaksi (bukan hanya pernyataan gagal) agar pernyataan sebelumnya diputar ulang pada transaksi baru. Untuk pola retry yang berorientasi produksi, lihat contoh di halaman utama driver PHP.
Kebuntuan yang berulang menunjukkan adanya masalah desain. Tangkap grafik deadlock dan analisis pernyataan serta tipe kunci yang terlibat. Perbaikan umum termasuk mengatur ulang operasi agar transaksi pesaing memperoleh kunci dalam urutan yang sama, mengurangi ruang lingkup transaksi, dan menambahkan indeks untuk mengurangi durasi kunci. Untuk panduan lengkap, lihat panduan Deadlocks.
Masalah ketahanan koneksi
Koneksi ulang tidak terjadi
Gejala:
Koneksi idle tetap terputus setelah failover Azure SQL Database, meskipun Anda mengatur ConnectRetryCount dan ConnectRetryInterval.
Kemungkinan penyebab dan solusi:
-
Kursor aktif di sisi server. Ketahanan koneksi idle hanya menghubungkan kembali koneksi idle . Kursor sisi server yang terbuka atau transaksi yang tertunda menjaga koneksi tetap aktif. Bebaskan kursor sisi server dengan menggunakan
sqlsrv_free_stmt()atau$stmt = null;(PDO) sebelum jendela failover, atau beralih ke kursor buffered sisi klien. Lihat Ketahanan koneksi saat idle. -
Status sesi yang tidak dapat dipulihkan. Beberapa status sesi tidak dapat dipulihkan, termasuk tabel sementara, kursor global dan lokal, konteks transaksi, kunci aplikasi,
EXECUTE AS/REVERThandle otomasi OLE, handle XML yang sudah disiapkan, dan flag trace. Salah satu status sesi ini mencegah koneksi ulang otomatis. -
LoginTimeoutterlalu kecil. JikaConnectRetryCount * ConnectRetryInterval > LoginTimeout, pengemudi berhenti mencoba ulang saatLoginTimeoutdicapai. NaikkanLoginTimeouthingga mencakup seluruh anggaran percobaan ulang.
Masalah performa
Untuk diagnosis dan penanganan kueri yang lambat, startup dingin, kumpulan hasil yang besar, dan penyisipan massal, lihat Performance tuning.
Aktifkan diagnostik driver
Ketika panggilan error_log() di tingkat aplikasi tidak memberikan informasi yang memadai, aktifkan pencatatan log di sisi driver. Laporan ini melaporkan setiap panggilan ODBC yang dilakukan pengemudi.
PDO_SQLSRV
Atur pdo_sqlsrv.log_severity di dalam php.ini dan mulai ulang server web. Pengaturan ini hanya dapat dibaca saat inisialisasi:
[pdo_sqlsrv]
pdo_sqlsrv.log_severity = 1
Nilainya adalah 0 (nonaktif, defaultnya), -1 (kesalahan, peringatan, dan pemberitahuan), 1 (kesalahan), 2 (peringatan), dan 4 (pemberitahuan).
SQLSRV
Aktifkan logging saat aplikasi berjalan dengan 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);
Entri log ditulis ke berkas yang dikonfigurasi oleh error_log di php.ini. Untuk daftar lengkap subsistem dan tingkat keparahan, lihat Aktivitas pencatatan.
Masalah kontainer dan CI
Pustaka sistem yang hilang di Linux
Gejala:
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
Perbaikan:
Instal dependensi runtime sebelum menginstal driver PHP:
| Distribution | Perintah instalasi |
|---|---|
| Ubuntu dan Debian | sudo apt-get install unixodbc libgssapi-krb5-2 |
| Red Hat dan Fedora | sudo dnf install unixODBC krb5-libs |
| Alpine | apk add unixodbc gcompat |
Kemudian instal msodbcsql18 dari repositori paket Microsoft. Untuk repositori dan versi paket khusus distribusi, lihat panduan instalasi driver ODBC.
Pembuatan image Docker berhasil, tetapi koneksi gagal saat dijalankan
Gejala:
Image berhasil dibangun dan PHP berhasil berjalan, tetapi PDO::__construct() menghasilkan kesalahan driver ODBC tidak ditemukan.
Perbaikan:
Pastikan driver ODBC terpasang di gambar runtime, bukan hanya pada tahap build. Pasang msodbcsql18 dan unixodbc-dev di tahap yang sama dengan pengiriman ke produksi. Dalam build bertahap, instalkan semuanya pada tahap akhir. Instalasi berbasis Debian satu tahap terlihat seperti ini:
# 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/*