PHP에서 MySQL에 연결하는 것은 매우 느립니다


19

방금 XAMPP를 새로 설치했습니다. PHPMyAdmin을 처음 열었을 때 나는 그것이 매우 느리다는 것을 알았습니다. localhost에서 모든 페이지가 열리려면 거의 5 초가 걸린다는 것은 말이되지 않았습니다. 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);

위의 스크립트는 실행하는 데 약 3 초가 걸립니다 (처음 실행했을 때로드하는 데 8 초가 더 걸렸습니다).

그런 다음 PDO의 결함인지 확인하기 위해 mysql_connect대신 사용하려고 했습니다.

$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');

완료하는 데 시간이 오래 걸립니다.

처음에는 PHP의 잘못이라고 생각했지만 새로 고침을 클릭 할 때보 다 PHP 코드와 정적 파일이 더 빠르게 제공됩니다. 이 작은 스크립트를 실행하여 PHP를 테스트했습니다.

header("Content-Type: text/plain");

for($i = 0; $i < 5000; $i++)
{
    echo sha1(rand()) . "\n";
}

5000 sha1계산 및 페이지가 여전히 창을 새로 고칠 수있는 것보다 더 빠르게 표시됩니다.

그런 다음 MySQL의 결함이라고 생각했습니다. 그러나 MySQL이 내가 필요로하는 것보다 빠르게 작동한다는 것을 알기 위해 많은 테스트를하지 않았습니다. MySQL CLI 클라이언트를 사용하면 사용자 선택 쿼리를 수행하는 데 시간이 오래 걸리지 않습니다. 리턴 키를 올리기 전에 수행됩니다.

문제는 PHP가 MySQL에 연결되어 있어야합니다. 내가 추론 할 수있는 한. PHP는 느리거나 MySQL은 느리다는 것을 알 수 있지만 PHP + MySQL은 매우 느립니다.

이 문제를 해결하도록 도와 줄 수있는 사람에게 감사합니다!


win32에 XAMPP 1.8.0을 사용하고 있습니다 ( 다운로드 링크 )
PHP 버전 : 5.4.4
MySQL 버전 : 14.14


편집 : 타이밍 후, 그것은 너무 오래 걸리는 연결 기능으로 밝혀졌습니다 :

$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);

산출:

연결 시간 : 1.006148
쿼리 시간 : 0.000247

PHP가 데이터베이스에 연결하는 데 많은 시간을 소비하게하는 원인은 무엇입니까? CLI 클라이언트, HeidiSQL 및 MySQL 워크 벤치가 즉시 연결


php -m 출력하시기 바랍니다
thinice

답변:


17

mysql은 연결할 때마다 rev-dns 쿼리를 실행하려고 시도 할 수 있습니까? my.cnf, mysqld : skip-name-resolve 섹션에 추가하십시오 .


이상하게도 PHPMyAdmin과 MySQL CLI 클라이언트 모두 "호스트 '127.0.0.1'은이 MySQL 서버에 연결할 수 없습니다." 어떤 이유로 PHP 스크립트는 여전히 작동하지만 이전처럼 느리다
Hubro

mysql Workbench와 같은 mysql을 관리하기위한 '뚱뚱한 응용 프로그램'은 느린가요?
pQd

MySQL Workbench에서 동일한 쿼리를 실행하는 것은 CLI 클라이언트만큼 빠르며 HeidiSQL도 마찬가지입니다.
Hubro

PHP에 타이밍을 추가하고 많은 시간이 걸리는 쿼리를 연결하거나 실행 중인지 확인하십시오.
pQd

그 의견에 감사드립니다. 내 질문을 업데이트했습니다. 연결과 쿼리 모두 초고속
Hubro

30

이 내 대답에서 거의 그대로 촬영 여기에 ,하지만 난 너희들에게 할뿐만 아니라 상상 그래서 나는 SO에 링크 전용 답변에 우리를 싫은 내색을 알고 :-)

이 문제가 발생하고 Windows 7 이전의 Windows 버전을 사용하는 경우 이는 문제의 답이 아닙니다.

왜 이런 일이 발생합니까?

이 문제의 원인은 IPv4와 IPv6입니다.

IP 주소 대신 호스트 이름을 사용하는 경우 MySQL 클라이언트는 먼저 AAAA이름에 대한 (IPv6) 호스트 조회를 실행하고 이름이 IPv6 주소로 성공적으로 확인되면이 주소를 먼저 시도합니다. 두 단계 중 하나라도 실패하면 (이름 확인 또는 연결) IPv4로 대체되어 A조회를 실행 하고이 호스트를 대신 시도합니다.

이것이 실제로 의미하는 것은 IPv6 localhost조회는 성공하지만 MySQL이 IPv6 루프백에 바인딩되지 않은 경우 IPv4 폴 백이 발생하고 연결이 성공하기 전에 하나의 연결 시간 초과주기를 기다려야한다는 것입니다.

localhost호스트 파일을 통해 확인이 완료 되었기 때문에 Windows 7 이전에는 문제가되지 않았으며 미리 구성되어 제공 되었기 때문에 127.0.0.1IPv6과 함께 제공되지 않았습니다 ::1.

그러나 Windows 7부터는 localhostDNS 확인 프로그램에 해결 방법이 기본적으로 제공 됩니다 . 즉, IPv6 조회는 성공하지만 MySQL은 해당 IPv6 주소에 바인딩되지 않으므로 연결이 실패하며이 질문에 요약 된 지연이 표시됩니다.

좋은 데요 이미 문제를 해결하는 방법을 알려주십시오!

몇 가지 옵션이 있습니다. 인터넷을 둘러 보면 일반적인 "솔루션"은 이름 대신 IP 주소를 명시 적으로 사용하는 것으로 보이지만, 이식성이 관련되지 않은 두 가지 이유가 있습니다.

  • IPv6 지원 하는 다른 컴퓨터로 스크립트를 이동 하면 더 이상 스크립트가 작동하지 않습니다.

  • 스크립트를 * nix 기반 호스팅 환경으로 옮길 경우, 마법 문자열 localhost은 MySQL 클라이언트가 구성되어있는 경우 Unix 소켓을 사용하는 것을 선호한다는 것을 의미합니다. 이는 IP 루프백 기반 연결보다 더 효율적입니다

그래도 꽤 중요하게 들리나요?

그렇지 않습니다. 이런 종류의 것이 구성 파일에 정의되도록 응용 프로그램을 설계해야합니다. 스크립트를 다른 환경으로 옮기면 다른 것들도 구성해야 할 가능성이 있습니다.

요약하면, IP 주소를 사용하는 것이 가장 좋은 해결책은 아니지만 수용 가능한 것입니다.

가장 좋은 해결책은 무엇입니까?

가장 좋은 방법은 MySQL 서버가 사용하는 바인드 주소를 변경하는 것입니다. 그러나 이것은 원하는만큼 간단하지 않습니다. Apache, Nginx 및 거의 모든 다른 제정신 네트워크 서비스 응용 프로그램과 달리 MySQL은 단일 바인드 주소 만 지원하므로 다른 주소를 추가하는 경우가 아닙니다. 운 좋게도 운영 체제는 여기에서 약간의 마술을 지원하므로 MySQL이 IPv4와 IPv6을 동시에 사용할 수 있습니다.

MySQL 5.5.3 이상을 실행해야하며 --bind-address=명령 행 인수로 MySQL을 시작해야합니다 . 수행하려는 작업에 따라 4 가지 옵션 문서 가 있습니다.

  • 당신은 아마 잘 알고 있고, 가장 효과적으로 (효과적으로) 사용하는 것 0.0.0.0입니다. 이것은 머신에서 사용 가능한 모든 IPv4 주소에 바인딩됩니다. IPv6에 관심이없는 경우에도 실제로는이 방법이 최선의 방법이 아닙니다 ::.

  • 명시 적 IPv4 또는 IPv6 주소 (예를 들어, 127.0.0.1또는 ::1루프백). 그러면 서버가 해당 주소와 해당 주소 에만 바인딩 됩니다 .

  • 마법의 문자열 ::. 이는 IPv4 및 IPv6 모드에서 MySQL을 머신의 모든 주소 (루프백 및 물리적 인터페이스 주소)에 바인딩합니다. 이것은 잠재적으로 보안 위험이 있으므로 원격 호스트의 연결을 수락하기 위해 MySQL이 필요한 경우에만 수행하십시오.

  • IPv4 매핑 된 IPv6 주소를 사용하십시오 . 이는 4-> 6 전환 동안 이전 버전과의 호환성을 위해 IPv6에 내장 된 특수 메커니즘이며 특정 IPv4 주소에 바인딩 할 수 있으며 IPv6에 상응합니다. 이것은 "이중 루프백"주소 이외의 다른 용도로는 유용하지 않을 것 ::ffff:127.0.0.1입니다. 이것은 대부분의 사람들에게 최상의 솔루션 일 것입니다. 루프백에만 바인딩하고 IPv4 및 IPv6 연결을 모두 허용합니다.

hosts 파일을 수정해야합니까?

아니요 . hosts 파일을 수정하지 마십시오. DNS 리졸버는 무엇을해야할지 알고 localhost, 그것을 재정의해도 아무런 효과가 없으며 최악의 경우 리졸버를 혼란스럽게합니다.

무엇에 대해 --skip-name-resolve?

관련이 있지만 약간 다른 이유로 문제를 해결할 수도 있습니다.

이 구성 옵션이 없으면 MySQL은 PTRDNS 쿼리 를 통해 모든 클라이언트 연결 IP 주소를 호스트 이름으로 확인 하려고 시도 합니다. MySQL 서버에서 이미 IPv6을 사용할 수 있지만 연결 시간이 오래 걸리면 역방향 DNS ( PTR) 레코드가 올바르게 구성되지 않았기 때문일 수 있습니다 .

이름 확인을 비활성화하면이 문제가 해결되지만 다른 결과가 있습니다. 특히 Host조건 에서 DNS 이름을 사용하도록 구성된 모든 액세스 권한 이 실패합니다.

이 작업을 수행하려면 이름 대신 IP 주소를 사용하도록 모든 권한을 구성해야합니다.


2
드디어! 감사합니다 감사합니다 마침내 나는 모든 원인, 가능한 해결책 및 그들의 반박에 대한 적절하고 완전하고 명확한 설명을 발견했습니다. 그것에 관한 책을 써야합니다!
tobia.zanarella

4
bind-address를로 변경할 때까지 localhost에서 MySQL에 연결하는 데 1 초 지연이 발생했습니다 ::1. 불행히도 ::ffff:127.0.0.1(사용 여부에 관계없이) 1 초 지연이 계속 발생했습니다. skip-name-resolve어떻게 생각하십니까? (Windows 8.1)
Simon East

1
@Simon 눈에 띄지 않는 단서가 아니지만 디버깅의 첫 단계는 명시 적 주소를 사용하여 IPv6 루프백과 IPv4 루프백에 직접 연결하여 MySQL이 실제로 두 스택에서 수신 대기하고 연결 가능한지 확인하는 것입니다. .
DaveRandom

1
yea, :: ffff : 127.0.0.1이 작동하지 않습니다 ...
Raheel Hasan

:: 1과 바인딩하면 Sqlyog가 작동하지 않습니다 ... 어떻게해야합니까 ??
Raheel Hasan

13

일반적으로 MySQL에 대한 서버 연결에서 IPv6이 활성화 된 경우 사용 localhost속도가 매우 느립니다.

스크립트에서 mysql 서버 주소를 변경하면 127.0.0.1문제가 해결됩니다.


+1 이것은 정답입니다. 나는 Windows 8에서 localhost@DaveRandom이 다음과 같은 이유로 DNS 확인 자로 해상도를 이동 했다고 생각합니다. serverfault.com/questions/4689/…
wwarren

그것은 나를 위해 일했다 : D
FosAvance

이 이외의 다른 서버에서 발생할 수 있습니다 localhost. 양식의 서버 주소에 대해 동일한 지연 문제가있었습니다 xx.xxxx.xxxxx.xxxxx.com. 서버 이름을 IP 주소로 변경하면 문제가 사라졌습니다.
Gruber

1
mysql_connect("localhost", "root", "");

그 이유가 무엇인지는 분명합니다. PHP는 실제로는 잘하지만 'localhost'를 '127.0.0.1'로 직접 번역하는 것은 아닙니다. HOSTS 파일 확인에서 PHP를 다시 보류하고 'localhost'뒤에 실제 IP 주소를 가져 오기 위해 수행하지 않는 작업을 수행하므로 전체 웹 사이트 페이지 로딩 시간이 실제로 단축됩니다.


문제가 무엇인지 제안하려는 것을 알 수 없습니다.
kasperd

@kasperd 'localhost'의 DNS 분석
Xesau

'17-note-mysql_ * 함수는 더 이상 사용되지 않으며 php7에서 제거되었습니다.
treyBake


0

또한 db 연결 변수를 약간 조정하여 쿼리 속도 저하를 제거 할 수 있습니다 (이동성을 위해 스크립트와 별도의 파일에 있기를 바랍니다). 호스트 값을 "localhost"대신 "127.0.0.1"로 변경하십시오. 이것은 로컬 호스트에 대한 긴 DNS 조회를 무시합니다.

도움이 되었기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.