PDO 폐쇄 연결


120

MySQLi에 비해 PDO와 관련하여 다소 간단한 질문입니다.

MySQLi를 사용하여 연결을 닫으려면 다음을 수행 할 수 있습니다.

$this->connection->close();

그러나 PDO에서는 다음을 사용하여 연결을 엽니 다.

$this->connection = new PDO();

하지만 연결을 닫으려면로 설정합니다 null.

$this->connection = null;

이것이 정확하고 실제로 PDO 연결을 해제합니까? (로 설정되어 있다는 것을 알고 있습니다 null.) MySQLi close에서는 연결을 닫으려면 함수 ( )를 호출 해야합니다. PDO는 = null연결 해제 만큼 쉬운가요 ? 아니면 연결을 끊는 기능이 있습니까?


11
내가 묻는 이유는 연결을 제대로 닫고 있는지 확실하지 않기 때문입니다. 하지만 정말 흥미 없습니다
리암 Sorsby에게

2
PHP 스크립트가 실행을 중지하면 데이터베이스 연결이 자동으로 닫힙니다.
Martin Bean

3
사용을 마쳤다면, 특히 데이터베이스와의 상호 작용을 마친 후 시간이 많이 걸리는 코드가있는 경우 계속해서 종료하지 마십시오. 하지만 스크립트가 완료 될 때까지 기다리는 문제는 실제로 보이지 않습니다 (DB 서버에 대한 연결을 줄이는 것 외에는)
Kieran

3
github.com/php/php-src/blob/master/ext/pdo/pdo_dbh.c 어떻게 작동하는지 직접 알아보세요 : P
Flosculus 2013-08-16

23
모든 PHP 스크립트가 수명이 짧은 것은 아닙니다. 거기에 PHP 데몬이 있습니다. 나는 이것이 개인적으로 명확히하는 좋은 일이라고 생각한다.
datUser

답변:


146

문서에 따르면 정확합니다 ( http://php.net/manual/en/pdo.connections.php ) :

연결은 해당 PDO 개체의 수명 동안 활성 상태로 유지 됩니다. 연결을 닫으려면 나머지 참조가 모두 삭제되었는지 확인 하여 개체제거 해야 합니다. 개체를 보유하는 변수에 NULL을 할당하여이를 수행합니다. 이 작업을 명시 적으로 수행하지 않으면 스크립트가 종료 될 때 PHP가 자동으로 연결을 닫습니다 .

PDO 개체를 영구 연결로 초기화하면 연결이 자동으로 닫히지 않습니다.


4
끝나지 않는 프로세스가 있으면 어떻게합니까? 예 : websocket. 영구 연결을 사용하지 않는 방법이 있습니까?
Rafael Moni 2015

1
오랜 기간 동안 실행되는 스크립트의 지속적인 연결의 경우 의도적으로 (또는 실수로) 제한 시간 (예 : my.ini) 또는 기타 여러 이유로 연결이 종료 될 수 있습니다. 쿼리를 연결하거나 실행할 때 오류를 포착하고 "MySQL이 사라졌습니다"인 경우 다시 연결을 시도하거나 쿼리를 다시 실행합니다.
Frank Forte

1
Note that if you initialise the PDO object as a persistent connection it will not automatically close the connection그러나 연결이 영구적이고 스크립트가 끝나기 전에 명시 적으로 NULL을 호출하면 영구적 인 경우에도 닫힙니다. 맞습니까?
tonix

1
@tonix 아니요, 릴리스되어야하지만 (다른 스크립트에서 사용 가능) 닫히지 않습니다.
Benjamin

2
@tonix 그렇게 생각합니다. 영구 연결에 대한 PHP 매뉴얼의 인용문 : " 경고 영구 연결을 사용할 때 명심해야 할 몇 가지 추가주의 사항이 있습니다. 하나는 영구 연결에서 테이블 잠금을 사용할 때 어떤 이유로 든 스크립트가 잠금을 해제 할 수없는 경우, 그러면 동일한 연결을 사용하는 후속 스크립트는 무기한 차단되며 httpd 서버 또는 데이터베이스 서버를 다시 시작해야 할 수 있습니다. "
Benjamin

46
$conn=new PDO("mysql:host=$host;dbname=$dbname",$user,$pass);
    // If this is your connection then you have to assign null
    // to your connection variable as follows:
$conn=null;
    // By this way you can close connection in PDO.

11
IMHO 특히 개발자가 pdo 참조의 여러 복사본을 저장할 때 매우 나쁜 패턴이라고 생각합니다. $ a = 새로운 PDO (...); $ b = $ a; $ a = null; 거기에서 PDO 객체는 (데몬과 같은 PHP 프로그램에서) 영원히 열려 있습니다. 특히 PDO 참조가 함수와 객체 속성을 가로 질러 이동할 때 특히 그렇습니다.
가브리엘

33
PDO에는-> close () 메소드가 있어야합니다.
가브리엘

5
PDO를 싫어하는 또 다른 이유.
José Carlos PHP

6
@Gabriel- "여러 복사본 저장"이 더 나쁜 패턴이라고 제안합니다.
Rick James

4
두 행 사이에 (즉, 모든 실제 상황에서) PDOStatement 개체를 만든 경우에는 작동하지 않습니다. 연결을 닫으려면 PDO 개체와 PDOStatement 개체를 모두 null로 설정해야합니다. 여기를보십시오 : php.net/manual/en/pdo.connections.php#114822
Ilmari

8

연결을 null로 설정하는 것 이상입니다. 문서에 나와있는 내용 일 수 있지만 mysql에 대한 진실은 아닙니다. 연결이 조금 더 오래 지속됩니다 (60 초를 들었지만 테스트 한 적은 없음).

여기에서 전체 설명을 보려면 연결 https://www.php.net/manual/en/pdo.connections.php#114822 에 대한이 주석을 참조하십시오.

강제로 연결을 끊으려면 다음과 같이해야합니다.

$this->connection = new PDO();
$this->connection->query('KILL CONNECTION_ID()');
$this->connection = null;

답변 주셔서 감사합니다. 질문은 꽤 오래전에서 왔지만 연결에 대한 귀하의 권리입니다.
Liam Sorsby

나는 실제로 PHP를 통한 TCP 연결을 엉망으로 만드는 것이 좋은 생각이라는 데 동의하지 않습니다. 모든 낮은 수준의 TCP 연결 처리는 추상화되어 런타임 동안 높은 수준의 클래스와 개체 만 처리하면됩니다. PHP는 (아시겠지만) 요청 기반 언어이므로 dB에 대한 잠재적 인 지속적인 연결을 중단하면 사용자에게 예기치 않은 오류 / 문제가 발생할 수 있습니다. 링크하는 사용 사례는 드라이버가 영구 연결을 열어 다른 요청에 의해 활용되는 결과 일 가능성이 있으므로 이것이 예상되는 동작이라고 생각했을 것입니다.
Liam Sorsby

실제로 mysql의 프로세스 목록을 보면 연결이 여전히 표시됩니다. 이렇게 TCP 연결을 엉망으로 만들지 말아야한다는 데 동의하며 연결을 제대로 끊을 수있는 방법이 있어야합니다. 그러나 그것은 사실이 아닙니다. 따라서 정말로 서버와의 연결을 끊으려면 이와 같은 작업을 수행해야합니다. 연결을 null로 설정해도 문서가 말하는 것과는 반대로 연결이 끊어지지 않습니다.
Jdahern

나는이 explaination를 발견했습니다 stackoverflow.com/a/18277327/1315873

7

"$ conn = null;"대신 자체 문서화 지침이있는 파생 클래스를 만들었습니다.

class CMyPDO extends PDO {
    public function __construct($dsn, $username = null, $password = null, array $options = null) {
        parent::__construct($dsn, $username, $password, $options);
    }

    static function getNewConnection() {
        $conn=null;
        try {
            $conn = new CMyPDO("mysql:host=$host;dbname=$dbname",$user,$pass);
        }
        catch (PDOException $exc) {
            echo $exc->getMessage();
        }
        return $conn;
    }

    static function closeConnection(&$conn) {
        $conn=null;
    }
}

그래서 다음 사이에서 내 코드를 호출 할 수 있습니다.

$conn=CMyPDO::getNewConnection();
// my code
CMyPDO::closeConnection($conn);

1
당신은 할 수 있습니다 CMyPDO :: __ 구조 () 메소드 개인 및 사용 싱글 톤 패턴이 ..
아 디트 Hajare

예, 가능합니다. 또한 한 번에 둘 이상의 데이터베이스를 사용하는 경우 다른 방법으로 연결 정보를 할당해야합니다. 차이는 미미합니다. 인스턴스 메서드를 호출하는 데 필요한 지침이 거의 없습니다.

... 당신은 하위 클래스에서 개인 슈퍼 클래스의 공개 방법을 만들 수 없습니다 @AdityaHajare
nickdnk

@ nickdnk, 당신이 맞습니다. 내가 의미하는 바는 독립 실행 형 클래스 CMyPDO (PDO를 확장하지 않고)를 만든 다음 CMyPDO의 개인 생성자 (new PDO ($ dsn, $ dbuser, $ dbpass);) 내에 데이터베이스 인스턴스를 생성하여 하나만 확인하는 것입니다. 인스턴스는 응용 프로그램 전체에서 사용할 수 있습니다 (Singleton Design Pattern).
Aditya Hajare

1
@Fil 그러나 "외부"코드 closeConnection는 객체를 할당하는 대신 변수에 대한 참조를 복사해야한다는 것을 인식해서는 안됩니다. 즉, close PDO 함수를 코딩하는 방법은 나쁜 부작용이있어 신뢰할 수 없습니다. 그렇게하는 유일한 방법 closeConnection은 코드에 PDO 개체에 대한 참조가 몇 개 있는지 확인하고 1 개 이상이있는 경우 throw하는 것입니다.
Xenos

-1
<?php if(!class_exists('PDO2')) {
    class PDO2 {
        private static $_instance;
        public static function getInstance() {
            if (!isset(self::$_instance)) {
                try {
                    self::$_instance = new PDO(
                        'mysql:host=***;dbname=***',
                        '***',
                        '***',
                        array(
                            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_general_ci",
                            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION
                        )
                    );
                } catch (PDOException $e) {
                    throw new PDOException($e->getMessage(), (int) $e->getCode());
                }
            }
            return self::$_instance;
        }
        public static function closeInstance() {
            return self::$_instance = null;
        }
    }
}
$req = PDO2::getInstance()->prepare('SELECT * FROM table');
$req->execute();
$count = $req->rowCount();
$results = $req->fetchAll(PDO::FETCH_ASSOC);
$req->closeCursor();
// Do other requests maybe
// And close connection
PDO2::closeInstance();
// print output

사용자 정의 클래스 PDO2를 사용한 전체 예제.


1
코드에서 try catch를 제거하거나 여기에 표시된대로 내부에 새 throw를 추가 하십시오 . 현재 귀하의 코드는 일반적으로 예외와 오류보고를 모두 남용합니다
상식
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.