복붙노트

PDO에서 지속적 연결을 사용할 경우의 단점은 무엇입니까?

PHP

PDO에서 지속적 연결을 사용할 경우의 단점은 무엇입니까?

PDO에서는 PDO :: ATTR_PERSISTENT 속성을 사용하여 연결을 지속시킬 수 있습니다. PHP 매뉴얼에 따르면 -

또한 ODBC 연결 풀링 프로세스를 방해 할 수 있으므로 PDO ODBC 드라이버를 사용하는 동안 지속적 연결을 사용하지 않는 것이 좋습니다.

따라서 마지막 경우를 제외하고 PDO에서 지속적인 연결을 사용하는 데는 단점이없는 것으로 보입니다. 그러나이 메커니즘을 사용하는 데있어 다른 단점이 있는지, 즉이 메커니즘으로 인해 성능이 저하되는 상황이 있는지 알고 싶습니다.

해결법

  1. ==============================

    1.아래에 나와있는 문제를 완화하는 방법을 자세히 설명하는이 답변을 꼭 읽어보십시오.

    아래에 나와있는 문제를 완화하는 방법을 자세히 설명하는이 답변을 꼭 읽어보십시오.

    영구적 인 연결을 수행하는 다른 PHP 데이터베이스 인터페이스와 마찬가지로 PDO를 사용하는 경우에도 같은 단점이 있습니다. 스크립트가 데이터베이스 작업 중간에 예기치 않게 종료되는 경우 연결이 남아있는 다음 요청은 죽은 스크립트가 중단 된 곳을 선택합니다. PHP 레벨이 아닌 프로세스 관리자 레벨 (mod_php의 경우 아파치, FastCGI를 사용하는 경우 현재의 FastCGI 프로세스 등)에서 연결이 열려 있으며, PHP는 부모 프로세스에게 연결이 끊어 지도록 지시하지 않습니다. 스크립트가 비정상적으로 종료됩니다.

    죽은 스크립트가 테이블을 잠근 경우 해당 테이블은 연결이 끊어 지거나 연결을 가져 오는 다음 스크립트가 테이블 자체의 잠금을 해제 할 때까지 잠긴 상태로 유지됩니다.

    죽은 스크립트가 트랜잭션 중간에 있었다면 교착 상태 타이머가 시작될 때까지 여러 테이블을 차단할 수 있습니다. 심지어 교착 상태 타이머가 문제를 일으키는 이전 요청 대신 새로운 요청을 죽일 수 있습니다.

    죽은 스크립트가 트랜잭션 중간에 있었다면 해당 연결을 가져 오는 다음 스크립트도 트랜잭션 상태를 가져옵니다. 다음 스크립트가 실제로 기존 트랜잭션을 커밋하려고 시도하지 않았거나 가질 필요가 없을 때 커밋하거나, 없어야 할 때 롤백 할 가능성이 매우 높습니다 (응용 프로그램 디자인에 따라 다름).

    이것은 빙산의 일각에 불과합니다. 항상 모든 단일 스크립트 요청에서 더티 연결 후 정리를 시도함으로써 어느 정도 완화 될 수 있지만 데이터베이스에 따라 고통이 될 수 있습니다. 스크립트에서 병목 현상이있는 데이터베이스 커넥션 생성 (xdebug 및 / 또는 xhprof를 사용한 코드 프로파일 링을 의미 함)이 아니라면 영구 연결을 모든 솔루션으로 간주해서는 안됩니다.

    게다가, 대부분의 최신 데이터베이스 (PostgreSQL 포함)에는 바닐라 PHP 기반의 영구 연결이하는 즉각적인 단점이없는 연결 풀링을 선호하는 방법이 있습니다.

    요점을 명확히하기 위해 우리는 직장에서 영구적 인 연결을 사용하지만 선택으로 연결하지 않습니다. 이상한 연결 동작이 발생했습니다. 앱 서버에서 데이터베이스 서버로의 초기 연결은 초당 몇 분의 일이 걸렸을 때 정확히 3 초가 걸렸습니다. 커널 버그라고 생각합니다. 무작위로 발생했기 때문에 문제를 해결하기를 포기하고 요청에 따라 재생산 할 수 없었으며 아웃소싱 된 IT 부서는이를 추적 할 수있는 구체적인 능력이 없었습니다.

    어쨌든 창고에있는 사람들이 몇백 가지 들어오는 부분을 처리하고 각 부분이 0.5 초가 아닌 3 초 30 초가 걸릴 때 우리 모두가 납치되어 우리를 도와주기 전에 조치를 취해야했습니다. 그래서 우리는 자생적 인 ERP / CRM / CMS 괴물에서 몇 비트 뒤집어 놓았으며 영구 연결의 모든 공포를 직접 경험했습니다. 겉보기에 무작위로 일어난 모든 미묘한 작은 문제와 기괴한 행동을 추적하는 데 몇 주가 걸렸습니다. 사용자가 부지런히 앱에서 압박 해 버린 일주일에 한 번 치명적인 실수로 인해 잠긴 테이블, 버려진 거래 및 불행한 유복 한 상태가 떠돌 았던 것으로 밝혀졌습니다.

    이 침착 한 이야기는 요점을 가지고 있습니다. 우리가 결코 깨뜨릴 것으로 예상하지 못한 것들은 모두 성능의 이름으로 부러졌습니다. 절충안은 가치가 없었고, 우리는 사용자들의 폭동없이 정상적인 연결로 전환 할 수있는 날을 간절히 기다리고 있습니다.

  2. ==============================

    2.위의 Charles의 문제에 대한 응답으로,

    위의 Charles의 문제에 대한 응답으로,

    보낸 사람 : http://www.php.net/manual/en/mysqli.quickstart.connections.php -

    지속적인 연결에 대한 일반적인 불만은 재사용 전에 상태가 재설정되지 않는다는 것입니다. 예를 들어, 열려 있거나 완료되지 않은 트랜잭션은 자동으로 롤백되지 않습니다. 그러나 연결을 풀에 넣고 다시 사용하는 사이에 발생한 권한 변경은 반영되지 않습니다. 이것은 원하지 않는 부작용으로 간주 될 수 있습니다. 오히려 그 이름은 국가가 존속한다는 약속으로 이해 될 수 있습니다.

    mysqli 확장은 영속 연결의 해석을 모두 지원한다 : 상태가 지속되고 재사용되기 전에 상태가 재설정된다. 기본값은 재설정됩니다. 지속적인 연결이 재사용되기 전에, mysqli 확장은 암묵적으로 mysqli_change_user ()를 호출하여 상태를 재설정한다. 영구 연결은 방금 열린 것처럼 사용자에게 표시됩니다. 이전 사용법의 아티팩트는 표시되지 않습니다.

    mysqli_change_user () 함수는 값 비싼 연산이다. 최적의 성능을 위해 사용자는 컴파일 플래그 MYSQLI_NO_CHANGE_USER_ON_PCONNECT가 설정되어 확장을 다시 컴파일하고자 할 수 있습니다.

    안전 행동과 최상의 성능 중에서 선택하는 것은 사용자에게 맡겨져 있습니다. 둘 다 유효한 최적화 목표입니다. 사용의 편의성을 위해 최대 성능을 희생하여 안전 동작이 기본값으로 설정되었습니다.

  3. ==============================

    3.내 테스트에서 필자는 localhost에 대한 연결 시간이 1 초를 넘었다. 따라서 영구 연결을 사용해야한다고 가정했다. 추가 테스트 결과 'localhost'에 문제가 있다는 것을 알 수있었습니다.

    내 테스트에서 필자는 localhost에 대한 연결 시간이 1 초를 넘었다. 따라서 영구 연결을 사용해야한다고 가정했다. 추가 테스트 결과 'localhost'에 문제가 있다는 것을 알 수있었습니다.

    초 단위의 테스트 결과 (PHP 마이크로 시간으로 측정) :

    흥미롭게도 다음 코드는 127.0.0.1을 사용하는 것만큼이나 빠릅니다.

    $host = gethostbyname('localhost');
    // echo "<p>$host</p>";
    $db = new PDO("mysql:host=$host;dbname=" . DATABASE . ';charset=utf8', $username, $password,
        array(PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
    
  4. ==============================

    4.영구 연결은 데이터베이스에 연결하는 데 상대적으로 오랜 시간이 걸리는 경우에만 좋은 아이디어입니다. 요즘 거의 절대 그렇지 않습니다. 영구 연결의 가장 큰 단점은 사이트를 탐색 할 수있는 사용자의 수를 제한한다는 것입니다. MySQL이 한 번에 10 개의 동시 연결 만 허용하도록 설정 한 경우 11 번째 사용자가 사이트를 탐색하려고 시도 할 때 해당 사용자에게는 작동하지 않습니다 .

    영구 연결은 데이터베이스에 연결하는 데 상대적으로 오랜 시간이 걸리는 경우에만 좋은 아이디어입니다. 요즘 거의 절대 그렇지 않습니다. 영구 연결의 가장 큰 단점은 사이트를 탐색 할 수있는 사용자의 수를 제한한다는 것입니다. MySQL이 한 번에 10 개의 동시 연결 만 허용하도록 설정 한 경우 11 번째 사용자가 사이트를 탐색하려고 시도 할 때 해당 사용자에게는 작동하지 않습니다 .

    PDO는 지속성을 관리하지 않습니다. MySQL 드라이버가 않습니다. a) 사용 가능하고 호스트 / 사용자 / 암호 / 데이터베이스가 일치 할 때 연결을 다시 사용합니다. 변경이 있으면 연결을 다시 사용하지 않습니다. 가장 좋은 경우의 그물 효과는 사이트에서 다른 사용자를 보유하고 지속적으로 유지하는 것이 좋지 않기 때문에 이러한 연결을 자주 시작하고 중지한다는 것입니다.

    지속적인 연결에 대해 이해해야 할 핵심 사항은 대부분의 웹 응용 프로그램에서 사용하지 않아야한다는 것입니다. 유혹하는 것처럼 들리지만 그들은 위험하고 거의 쓸모가 없습니다.

    이 스레드에는 다른 스레드가 있지만 영구적 인 연결은 요청간에 지속되므로 위험합니다. 예를 들어 요청 중에 테이블을 잠근 다음 잠금을 해제하지 못하면 해당 테이블이 무기한으로 잠긴 상태로 유지됩니다. 영구 연결은 다른 요청간에 동일한 연결이 사용되는지 여부를 알 수 없으므로 앱의 99 %에서 거의 쓸모가 없습니다. 각 웹 스레드는 자체 연결 세트를 가지며 어떤 스레드가 어떤 요청을 처리할지 제어 할 방법이 없습니다.

    PHP의 프로 시저 mysql 라이브러리에는 mysql_connect에 대한 후속 호출이 다른 연결을 열지 않고 동일한 링크를 반환하는 기능이 있습니다 (예상대로). 이것은 지속적인 연결과는 아무런 관련이 없으며 mysql 라이브러리에만 적용됩니다. PDO는 그러한 행동을 나타내지 않습니다.

    리소스 링크 : 링크

    일반적으로 이것을 대략적인 "ruleset"으로 사용할 수 있습니다.

    예, 다음과 같은 경우 영구 연결을 사용하십시오.

    아니오, 영구 연결을 사용하지 마십시오.

    영구 연결을 사용하면 네트워크를 통해 데이터베이스에 액세스하는 경우 특히 더 빠릅니다. 데이터베이스가 동일한 시스템에서 실행되는 경우별로 차이는 없지만 조금 더 빠릅니다. 그러나 이름에서 알 수 있듯이 연결은 영구적입니다. 즉, 연결이 사용되지 않아도 열려 있습니다.

    문제는 "기본 설정"에서 MySQL은 1000 개의 병렬 "열린 채널"만 허용한다는 것입니다. 그 후에 새로운 연결이 거부됩니다 (이 설정을 조정할 수 있음). 따라서 각각 100 명의 클라이언트가있는 20 대의 웹 서버가 있고 시간당 한 페이지 만 액세스하면 간단한 수학을 통해 데이터베이스에 2000 개의 병렬 연결이 필요하다는 것을 알 수 있습니다. 그것은 작동하지 않습니다.

    Ergo : 많은 요청이있는 응용 프로그램에만 사용하십시오.

  5. ==============================

    5.영구 연결은 상당한 성능 향상을 제공해야합니다. 나는 당신이 "끈기"를 피해야한다는 평가에 동의하지 않습니다.

    영구 연결은 상당한 성능 향상을 제공해야합니다. 나는 당신이 "끈기"를 피해야한다는 평가에 동의하지 않습니다.

    위의 불만 사항이 MyIASM 테이블을 사용하고 테이블 잠금 장치를 잡아서 트랜잭션 버전을 해킹 한 것에서 비롯된 것 같습니다. 물론 물론 교착 상태에 빠질 것입니다! PDO의 beginTransaction ()을 사용하고 테이블을 InnoDB로 이동하십시오.

  6. ==============================

    6.지속적인 연결을하는 것이 시스템 리소스를 더 많이 차지하게하는 것 같습니다. 사소한 금액 일 수도 있지만 여전히 ...

    지속적인 연결을하는 것이 시스템 리소스를 더 많이 차지하게하는 것 같습니다. 사소한 금액 일 수도 있지만 여전히 ...

  7. ==============================

    7.영구 연결을 사용하는 것에 대한 설명은 분명히 다른 데이터베이스에 비해 MySQL을 사용하는 것이 훨씬 빠르다는 사실에도 불구하고 비용이 많이 드는 연결량을 줄입니다.

    영구 연결을 사용하는 것에 대한 설명은 분명히 다른 데이터베이스에 비해 MySQL을 사용하는 것이 훨씬 빠르다는 사실에도 불구하고 비용이 많이 드는 연결량을 줄입니다.

    지속적인 연결로 인한 첫 번째 문제 ...

    초당 1000 회의 연결을 생성하는 경우 일반적으로 매우 오랜 시간 동안 열어 두지 만 운영 체제에서는 열어 둘 수는 없습니다. TCP / IP 프로토콜 기반 포트는 즉시 재활용 될 수 없으며 "FIN"단계에서 재활용되기 전에 대기해야합니다.

    두 번째 문제는 ... 많은 MySQL 서버 연결을 사용하는 것입니다.

    많은 사람들이 * max_connections * 변수를 늘리고 MySQL과 100 개 이상의 동시 연결을 확보 할 수 있다는 것을 깨닫지 못합니다. 이전 Linux 문제로 인해 MySQL과 1024 개 이상의 연결을 전달할 수 없다는 사람들이있었습니다.

    mysqli 확장에서 영구 연결이 비활성화 된 이유에 대해 지금 이야기 할 수 있습니다. 사실 지속적인 연결을 오용하고 주된 이유가 아닌 성능 저하를 가져올 수 있다는 사실에도 불구하고. 실제 이유는 - 당신은 더 많은 문제를 가질 수 있습니다.

    영구 연결은 MySQL 3.22 / 3.23의 경우에 PHP로 처리되었습니다. MySQL이 그렇게 어렵지 않을 때 문제없이 쉽게 연결을 재사용 할 수 있습니다. 그러나 이후 버전에서는 문제의 양이 발생했습니다. 커밋되지 않은 트랜잭션이있는 연결을 재사용해야 문제가 발생합니다. 사용자 정의 문자 집합 구성으로 연결을 재사용하면 위험에 처하게 될뿐만 아니라 세션 변수마다 변환 될 가능성이 있습니다.

    지속적인 연결을 사용할 때의 한 가지 문제는 실제로 잘 확장되지 않는다는 것입니다. 5000 명의 사람들이 연결되어있는 사람들은 5000 개의 지속적인 연결이 필요합니다. 지속성에 대한 요구 사항을 없애기 위해서는 개인 연결이없는 상태에서 개인 연결을 공유 할 수있는 위치에 있기 때문에 유사한 연결 수량을 가진 10000 명의 사용자에게 서비스를 제공 할 수 있습니다.

  8. ==============================

    8.부분적으로 솔루션을 사용할 수 있는지 여부를 궁금해하고있었습니다. 시스템 사용량이 적을 때, 최대 한도까지 연결 풀을 만드는 데 시간을 할애 할 수 있습니다. 연결 풀을 넘겨 주거나 완료 할 때 죽일 수 있습니다. 백그라운드에서 새로운 연결을 만드는 중입니다. 최악의 경우, 이것은 링크를 설정하는 것이 제한 요소라고 가정하면 풀없이 연결을 생성하는 것만 큼 느려야합니다.

    부분적으로 솔루션을 사용할 수 있는지 여부를 궁금해하고있었습니다. 시스템 사용량이 적을 때, 최대 한도까지 연결 풀을 만드는 데 시간을 할애 할 수 있습니다. 연결 풀을 넘겨 주거나 완료 할 때 죽일 수 있습니다. 백그라운드에서 새로운 연결을 만드는 중입니다. 최악의 경우, 이것은 링크를 설정하는 것이 제한 요소라고 가정하면 풀없이 연결을 생성하는 것만 큼 느려야합니다.

  9. from https://stackoverflow.com/questions/3332074/what-are-the-disadvantages-of-using-persistent-connection-in-pdo by cc-by-sa and MIT license