IT story

PDO에서 영구 연결을 사용할 때의 단점은 무엇입니까

hot-time 2020. 5. 24. 10:51
반응형

PDO에서 영구 연결을 사용할 때의 단점은 무엇입니까


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

지속적인 연결은 스크립트 끝에서 닫히지 않지만 다른 스크립트가 동일한 자격 증명을 사용하여 연결을 요청하면 캐시되고 재사용됩니다. 영구 연결 캐시를 사용하면 스크립트가 데이터베이스와 통신해야 할 때마다 새 연결을 설정하는 오버 헤드를 피할 수있어 웹 응용 프로그램이 더 빨라집니다.

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

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


여기에 설명 된 문제를 완화하는 방법을 자세히 설명하는 아래이 답변 을 읽으 십시오.


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

사용 불능 스크립트 잠금 테이블 인 경우 해당 테이블은 연결이 끊어 지거나 연결을 얻는 다음 스크립트가 테이블 자체를 잠금 해제 할 때까지 잠금 상태로 유지됩니다.

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

데드 스크립트가 트랜잭션 중간에있는 경우 해당 연결을받는 다음 스크립트도 트랜잭션 상태를 가져옵니다. 응용 프로그램 디자인에 따라 다음 스크립트가 실제로 기존 트랜잭션을 커밋하려고 시도하지 않을 수도 있고, 그렇지 않은 경우 커밋하거나하지 말아야 할 때 롤백 할 수도 있습니다.

이것은 빙산의 일각에 불과합니다. 모든 단일 스크립트 요청에 대해 더티 연결 후 항상 정리를 시도하면 어느 정도까지 완화 할 수 있지만 데이터베이스에 따라 고통이 될 수 있습니다. 스크립트에서 병목 현상을 일으키는 것으로 데이터베이스 연결 작성을 식별하지 않은 경우 ( xdebug 및 / 또는 xhprof를 사용하여 코드 프로파일 링을 수행 했음을 의미 함 ) 지속적인 연결을 솔루션으로 고려 해서는 안됩니다 .

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


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

어쨌든 창고의 직원들이 수백 개의 들어오는 부품을 처리 할 때 각 부품이 0.5 초가 아닌 3 초 반 걸리는 경우, 우리를 모두 납치하고 우리를 돕기 전에 조치를 취해야했습니다. 그래서 우리는 집에서 자란 ERP / CRM / CMS 괴물에서 약간의 비트를 뒤집었고 지속적인 연결의 모든 공포를 직접 경험했습니다. 겉보기에 무작위로 발생한 모든 미묘한 작은 문제와 기괴한 행동을 추적하는 몇 주가 걸렸습니다 . 사용자가 앱에서 부지런히 짜낸 일주일에 한 번 치명적인 오류가 잠긴 테이블, 버려진 트랜잭션 및 기타 불행한 이상한 상태를 떠나는 것으로 나타났습니다.

이 Sob-Story는 한 가지 중요한 점을 가지고 있습니다. 그것은 우리가 결코 기대할 수없는 것들을 성능의 이름으로 깨뜨 렸습니다. 트레이드 오프는 그만한 가치가 없었으며 사용자의 폭동 없이도 정상적인 연결로 다시 전환 할 수있는 날을 간절히 기다리고 있습니다.


위의 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가 설정된 상태 에서 확장을 다시 컴파일 할 수 있습니다 .

안전한 행동과 최상의 성능 중에서 선택하는 것은 사용자의 몫입니다. 둘 다 유효한 최적화 목표입니다. 사용하기 쉽도록 최대 성능을 희생하면서 안전한 동작이 기본값으로 설정되었습니다.


내 테스트에서 로컬 호스트에 1 초 이상의 연결 시간이 있었으므로 영구 연결을 사용해야한다고 가정합니다. 추가 테스트는 'localhost'에 문제가 있음을 보여주었습니다.

초 단위의 테스트 결과 (php microtime으로 측정) :

  • 호스팅 된 웹 : connectDB : 0.0038912296295166
  • localhost : connectDB : 1.0214691162109 (1 초 이상 : localhost를 사용하지 마십시오!)
  • 127.0.0.1 : connectDB : 0.00097203254699707

흥미롭게도 : 다음 코드는 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));

Persistent connections are a good idea only when it takes a (relatively) long time to connect to your database. Nowadays that's almost never the case. The biggest drawback to persistent connections is that it limits the number of users you can have browsing your site: if MySQL is configured to only allow 10 concurrent connections at once then when an 11th person tries to browse your site it won't work for them.

PDO does not manage the persistence. The MySQL driver does. It reuses connections when a) they are available and the host/user/password/database match. If any change then it will not reuse a connection. The best case net effect is that these connections you have will be started and stopped so often because you have different users on the site and making them persistent doesn't do any good.

The key thing to understand about persistent connections is that you should NOT use them in most web applications. They sound enticing but they are dangerous and pretty much useless.

I'm sure there are other threads on this but a persistent connection is dangerous because it persists between requests. If, for example, you lock a table during a request and then fail to unlock then that table is going to stay locked indefinitely. Persistent connections are also pretty much useless for 99% of your apps because you have no way of knowing if the same connection will be used between different requests. Each web thread will have it's own set of persistent connections and you have no way of controlling which thread will handle which requests.

The procedural mysql library of PHP, has a feature whereby subsequent calls to mysql_connect will return the same link, rather than open a different connection (As one might expect). This has nothing to do with persistent connections and is specific to the mysql library. PDO does not exhibit such behaviour


Resource Link : link

In General you could use this as a rough "ruleset"::

YES, use persistent connections, if:

  • There are only few applications/users accessing the database, i.e. you will not result in 200 open (but probably idle) connections, because there are 200 different users shared on the same host.
  • The database is running on another server that you are accessing over the network

  • An (one) application accesses the database very often

NO, don't use persistent connections, if:

  • Your application only needs to access the database 100 times an hour.

  • You have many, many webservers accessing one database server

Using persistent connections is considerable faster, especially if you are accessing the database over a network. It doesn't make so much difference if the database is running on the same machine, but it is still a little bit faster. However - as the name says - the connection is persistent, i.e. it stays open, even if it is not used.

The problem with that is, that in "default configuration", MySQL only allows 1000 parallel "open channels". After that, new connections are refused (You can tweak this setting). So if you have - say - 20 Webservers with each 100 Clients on them, and every one of them has just one page access per hour, simple math will show you that you'll need 2000 parallel connections to the database. That won't work.

Ergo: Only use it for applications with lots of requests.


Persistent connections should give a sizable performance boost. I disagree with the assement that you should "Avoid" persistence..

It sounds like the complaints above are driven by someone using MyIASM tables and hacking in their own versions of transactions by grabbing table locks.. Well of course you're going to deadlock! Use PDO's beginTransaction() and move your tables over to InnoDB..


seems to me having a persistent connection would eat up more system resources. Maybe a trivial amount, but still...


The explanation for using persistent connections is obviously reducing quantity of connects that are rather costly, despite the fact that they're considerably faster with MySQL compared to other databases.

The very first trouble with persistent connections...

If you are creating 1000's of connections per second you normally don't ensure that it stays open for very long time, but Operation System does. Based on TCP/IP protocol Ports can’t be recycled instantly and also have to invest a while in “FIN” stage waiting before they may be recycled.

The 2nd problem... using a lot of MySQL server connections.

Many people simply don't realize you are able to increase *max_connections* variable and obtain over 100 concurrent connections with MySQL others were beaten by older Linux problems of the inability to convey more than 1024 connections with MySQL.

Allows talk now about why Persistent connections were disabled in mysqli extension. Despite the fact that you can misuse persistent connections and obtain poor performance which was not the main reason. The actual reason is – you can get a lot more issues with it.

Persistent connections were put into PHP throughout occasions of MySQL 3.22/3.23 when MySQL was not so difficult which means you could recycle connections easily with no problems. In later versions quantity of problems however came about – Should you recycle connection that has uncommitted transactions you take into trouble. If you recycle connections with custom character set configurations you’re in danger again, as well as about possibly transformed per session variables.

One trouble with using persistent connections is it does not really scale that well. For those who have 5000 people connected, you'll need 5000 persistent connections. For away the requirement for persistence, you may have the ability to serve 10000 people with similar quantity of connections because they are in a position to share individuals connections when they are not with them.


I was just wondering whether a partial solution would be to have a pool of use-once connections. You could spend time creating a connection pool when the system is at low usage, up to a limit, hand them out and kill them when either they've completed or timed out. In the background you're creating new connections as they're being taken. At worst case this should only be as slow as creating the connection without the pool, assuming that establishing the link is the limiting factor?

참고URL : https://stackoverflow.com/questions/3332074/what-are-the-disadvantages-of-using-persistent-connection-in-pdo

반응형