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.