Saya baru saja menginstal XAMPP. Ketika pertama kali membuka PHPMyAdmin saya perhatikan itu sangat lambat. Tidak masuk akal bahwa pada localhost itu harus memakan waktu hampir 5 detik untuk setiap halaman untuk dibuka. Saya membuat test case kecil untuk mengalihkan kesalahan dari PHPMyAdmin:
$con = new PDO("mysql:host=localhost;dbname=mysql", "root", "");
$statement = $con->query('SELECT host,user,password FROM user;');
$users = $statement->fetchAll(PDO::FETCH_ASSOC);
Script di atas hanya membutuhkan waktu sekitar 3 detik untuk dijalankan (walaupun butuh lebih dekat hingga 8 detik untuk memuat pertama kali saya menjalankannya.)
Kemudian untuk memeriksa apakah itu kesalahan PDO, saya mencoba menggunakan mysql_connect
:
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');
Membutuhkan waktu yang sangat lama untuk menyelesaikannya.
Saya pikir itu kesalahan PHP pada awalnya, tetapi kode PHP dan file statis dilayani lebih cepat daripada yang saya bisa klik refresh. Saya menguji PHP dengan menjalankan skrip kecil ini:
header("Content-Type: text/plain");
for($i = 0; $i < 5000; $i++)
{
echo sha1(rand()) . "\n";
}
5000 sha1
perhitungan dan halaman ini masih ditampilkan snappier daripada saya dapat menyegarkan jendela saya.
Lalu saya pikir itu salah MySQL. Tetapi sekali lagi, tidak perlu banyak pengujian untuk mengetahui bahwa MySQL bekerja lebih cepat daripada yang saya butuhkan. Menggunakan klien MySQL CLI permintaan pilih pengguna bahkan tidak mengambil waktu yang dapat diukur - itu dilakukan sebelum saya bahkan membiarkan kunci kembali.
Masalahnya harus koneksi PHP ke MySQL - itu sejauh yang saya bisa alasan. Saya dapat menemukan banyak hal tentang PHP yang lambat atau MySQL yang lambat, tetapi tidak ada tentang PHP + MySQL yang sangat lambat.
Terima kasih kepada siapa saja yang dapat membantu saya menyelesaikan masalah ini!
Saya menggunakan XAMPP 1.8.0 untuk win32 ( tautan Unduh )
Versi PHP: 5.4.4
Versi MySQL: 14.14
EDIT: Setelah penghitungan waktu, ternyata itu adalah fungsi koneksi yang memakan waktu begitu lama:
$time = microtime(true);
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$con_time = microtime(true);
$result = mysql_query('SELECT host,user,password FROM user;');
$sel_time = microtime(true);
printf("Connect time: %f\nQuery time: %f\n",
$con_time-$time,
$sel_time-$con_time);
Keluaran:
Waktu koneksi: 1,006148 Waktu permintaan: 0,000247
Apa yang bisa menyebabkan PHP menghabiskan banyak waktu melakukan koneksi ke database? Klien CLI, HeidiSQL dan meja kerja MySQL terhubung secara instan
Jawaban:
Mungkinkah mysql Anda mencoba menjalankan kueri rev-dns setiap kali Anda terhubung? coba tambahkan ke my.cnf, bagian mysqld: skip-name-resol .
sumber
Ini diambil hampir kata demi kata dari jawaban saya di sini , tapi saya tahu kami mengerutkan kening pada jawaban tautan saja pada SO jadi saya bayangkan kalian juga melakukannya :-)
Jika Anda mengalami masalah ini dan menggunakan versi Windows sebelum Windows 7, ini mungkin bukan jawaban untuk masalah Anda.
Mengapa ini terjadi?
Penyebab masalah ini adalah IPv4 vs IPv6.
Saat Anda menggunakan nama host alih-alih alamat IP, klien MySQL pertama kali menjalankan
AAAA
pencarian host (IPv6) untuk nama tersebut, dan mencoba alamat ini terlebih dahulu jika berhasil menyelesaikan nama menjadi alamat IPv6. Jika salah satu langkah gagal (resolusi nama atau koneksi) itu akan mundur ke IPv4, menjalankanA
pencarian dan mencoba host ini sebagai gantinya.Apa artinya ini dalam praktiknya adalah bahwa jika
localhost
pencarian IPv6 berhasil tetapi MySQL tidak terikat pada loopback IPv6, Anda perlu menunggu satu siklus waktu habis koneksi sebelum penurunan IPv4 terjadi dan koneksi berhasil.Ini bukan masalah sebelum Windows 7, karena
localhost
resolusi dilakukan melalui file hosts, dan itu datang dengan prakonfigurasi saja127.0.0.1
- itu tidak datang dengan rekan IPv6 itu::1
.Karena Windows 7, bagaimanapun,
localhost
resolusi dibangun ke resolver DNS, untuk alasan yang diuraikan di sini . Ini berarti bahwa pencarian IPv6 sekarang akan berhasil - tetapi MySQL tidak terikat ke alamat IPv6 itu, sehingga koneksi akan gagal, dan Anda akan melihat penundaan yang diuraikan dalam pertanyaan ini.Itu bagus. Katakan padaku bagaimana cara memperbaikinya!
Anda punya beberapa pilihan. Melihat-lihat internet, "solusi" umum tampaknya adalah menggunakan alamat IP secara eksplisit alih-alih nama, tetapi ada beberapa alasan untuk tidak melakukan ini, baik terkait portabilitas, keduanya bisa dibilang tidak penting:
Jika Anda memindahkan skrip Anda ke komputer lain yang hanya mendukung IPv6, skrip Anda tidak akan berfungsi lagi.
Jika Anda memindahkan skrip Anda ke lingkungan hosting berbasis * nix, string ajaib
localhost
berarti klien MySQL akan lebih suka menggunakan soket Unix jika dikonfigurasi, ini lebih efisien daripada konektivitas berbasis loopback IPKedengarannya sangat penting?
Mereka bukan. Anda harus mendesain aplikasi Anda sehingga hal-hal semacam ini didefinisikan dalam file konfigurasi. Jika Anda memindahkan skrip ke lingkungan lain, kemungkinan hal-hal lain juga perlu dikonfigurasikan.
Singkatnya, menggunakan alamat IP bukanlah solusi terbaik , tetapi kemungkinan besar merupakan solusi yang dapat diterima.
Jadi apa solusi terbaik?
Cara terbaik adalah mengubah alamat bind yang digunakan oleh server MySQL. Namun, ini tidak sesederhana yang diinginkan. Tidak seperti Apache, Nginx dan hampir setiap aplikasi layanan jaringan waras lainnya yang pernah dibuat, MySQL hanya mendukung satu alamat pengikatan, jadi ini bukan hanya kasus menambahkan yang lain. Untungnya, sistem operasi mendukung sedikit keajaiban di sini, sehingga kita dapat mengaktifkan MySQL untuk menggunakan IPv4 dan IPv6 secara bersamaan.
Anda harus menjalankan MySQL 5.5.3 atau yang lebih baru, dan Anda harus memulai MySQL dengan
--bind-address=
argumen baris perintah. Anda memiliki 4 opsi dokumen , tergantung pada apa yang ingin Anda lakukan:Yang mungkin Anda kenal, dan yang paling mungkin Anda gunakan (secara efektif)
0.0.0.0
,. Ini mengikat semua alamat IPv4 yang tersedia pada mesin. Ini sebenarnya mungkin bukan hal terbaik untuk dilakukan bahkan jika Anda tidak peduli dengan IPv6, karena memiliki risiko keamanan yang sama::
.Alamat IPv4 atau IPv6 eksplisit (misalnya
127.0.0.1
atau::1
untuk loopback). Ini mengikat server ke alamat itu dan hanya alamat itu.Senar ajaib
::
. Ini akan mengikat MySQL ke setiap alamat pada mesin, baik loopback dan alamat antarmuka fisik, dalam mode IPv4 dan IPv6. Ini berpotensi risiko keamanan, hanya lakukan ini jika Anda memerlukan MySQL untuk menerima koneksi dari host jarak jauh.Gunakan alamat IPv6 yang dipetakan IPv4 . Ini adalah mekanisme khusus yang dibangun ke dalam IPv6 untuk kompatibilitas mundur selama transisi 4 -> 6, dan ini memungkinkan Anda mengikat ke alamat IPv4 tertentu dan setara dengan IPv6. Ini sangat tidak mungkin berguna bagi Anda untuk apa pun selain alamat "loopback ganda"
::ffff:127.0.0.1
. Ini kemungkinan besar merupakan solusi terbaik bagi kebanyakan orang, hanya mengikat ke loopback tetapi memungkinkan koneksi IPv4 dan IPv6.Apakah saya perlu memodifikasi file host?
TIDAK . Jangan memodifikasi file host. Penyelesai DNS tahu apa yang harus dilakukan
localhost
, mendefinisikan ulang paling tidak akan berpengaruh, dan paling buruk membingungkan para penyelesai.Bagaimana dengan
--skip-name-resolve
?Ini juga dapat memperbaiki masalah, karena alasan terkait tetapi sedikit berbeda.
Tanpa opsi konfigurasi ini, MySQL akan berusaha untuk menyelesaikan semua alamat IP koneksi klien ke nama host melalui
PTR
permintaan DNS. Jika server MySQL Anda sudah diaktifkan untuk menggunakan IPv6 tetapi koneksi masih membutuhkan waktu lama, itu mungkin karena catatan reverse DNS (PTR
) tidak dikonfigurasi dengan benar.Menonaktifkan resolusi nama akan memperbaiki masalah ini, tetapi memiliki konsekuensi lain, terutama bahwa izin akses yang dikonfigurasi untuk menggunakan nama DNS dalam
Host
kondisi sekarang akan gagal.Jika Anda akan melakukan ini, Anda harus mengonfigurasi semua hibah Anda untuk menggunakan alamat IP dan bukan nama.
sumber
::1
. Sayangnya::ffff:127.0.0.1
terus memberi saya penundaan 1 detik (terlepas dari menggunakanskip-name-resolve
atau tidak), ada ide mengapa? (pada Windows 8.1)Biasanya ketika IPv6 diaktifkan di koneksi server ke MySQL menggunakan
localhost
sangat lambat.Mengubah alamat server mysql di skrip untuk
127.0.0.1
menyelesaikan masalah.sumber
localhost
ke resolver DNS dengan alasan @DaveRandom ditautkan ke: serverfault.com/questions/4689/…localhost
. Saya memiliki masalah keterlambatan yang sama untuk alamat server pada formulirxx.xxxx.xxxxx.xxxxx.com
. Setelah saya mengubah nama server ke alamat IP-nya, masalahnya hilang.Yah, cukup jelas apa alasannya. PHP benar-benar bagus dalam beberapa hal, tetapi tidak secara langsung menerjemahkan 'localhost' ke '127.0.0.1'. Anda harus mencobanya, itu akan benar-benar menurunkan waktu pemuatan keseluruhan halaman situs web Anda, karena itu menahan PHP dari memeriksa file HOSTS Anda dan apa yang tidak dilakukan untuk mendapatkan alamat IP asli di belakang 'localhost'
sumber
Menambahkan baris ini ke file host Anda memecahkan masalah bagi saya
Jawaban terperinci dapat ditemukan di utas ini: /programming/13584360/php-with-mysql-is-slow
sumber
Anda juga dapat menghilangkan perlambatan kueri dengan membuat sedikit penyesuaian pada variabel koneksi db Anda (yang diharapkan dalam file terpisah dari skrip Anda untuk portabilitas). Ubah nilai host menjadi "127.0.0.1" alih-alih "localhost". Ini memintas pencarian DNS yang panjang untuk localhost.
Semoga ini membantu!
sumber