PDO: MySQL 서버가 사라졌습니다.
나는 밤에 많은 다리 작업을 하는 대본을 가지고 있다.
루프 내에서 실행되는 PDO 준비 스테이트먼트를 사용합니다.
첫 번째 몇 개는 정상적으로 동작하고 있지만, "MySQL server has away"라는 오류와 함께 모두 장애가 발생합니다.
MySQL 5.0.77을 실행하고 있습니다.
PHP 버전 5.2.12
나머지 사이트는 정상적으로 운영됩니다.
서버에 허가된 최대 패킷보다 긴 패킷을 송신했을 가능성이 높습니다.
를 삽입하려고 하면BLOB
서버의 최대 패킷사이즈를 초과하는 경우 로컬서버에서도 클라이언트측에서 다음 에러 메세지가 표시됩니다.
MySQL 서버가 사라졌습니다.
또한 서버 로그에 다음 오류 메시지가 표시됩니다(오류 로깅이 활성화되어 있는 경우).
오류 1153 'max_allowed_packet' 바이트보다 큰 패킷을 받았습니다.
이 문제를 해결하려면 가장 큰 크기를 결정해야 합니다.BLOB
삽입할 수 있고, 세팅할 수 있는max_allowed_packet
에my.ini
예를 들어 다음과 같습니다.
[mysqld]
...
max_allowed_packet = 200M
...
B.5.2.9. MySQL 매뉴얼의 MySQL Server has away 섹션에는 이 오류의 가능한 원인이 나와 있습니다.
그런 상황 중 하나일지도 모릅니다.특히 장기 수술을 하고 있는 것을 생각하면, 요점은 흥미로울지도 모릅니다.
타임아웃이 발생하면 호스팅 서버 관리에서 연결이 끊어지는 것과 같은 문제가 있었습니다.
주로 쿼리를 사용했기 때문에 PDO 클래스를 사용하는 대신 아래의 클래스를 포함하고 클래스 이름을 "Connection Manager PDO"로 바꿀 수 있는 코드를 작성했습니다.방금 PDO 수업을 끝냈어요.
final class ConnectionManagerPDO
{
private $dsn;
private $username;
private $passwd;
private $options;
private $db;
private $shouldReconnect;
const RETRY_ATTEMPTS = 3;
public function __construct($dsn, $username, $passwd, $options = array())
{
$this->dsn = $dsn;
$this->username = $username;
$this->passwd = $passwd;
$this->options = $options;
$this->shouldReconnect = true;
try {
$this->connect();
} catch (PDOException $e) {
throw $e;
}
}
/**
* @param $method
* @param $args
* @return mixed
* @throws Exception
* @throws PDOException
*/
public function __call($method, $args)
{
$has_gone_away = false;
$retry_attempt = 0;
try_again:
try {
if (is_callable(array($this->db, $method))) {
return call_user_func_array(array($this->db, $method), $args);
} else {
trigger_error("Call to undefined method '{$method}'");
/*
* or
*
* throw new Exception("Call to undefined method.");
*
*/
}
} catch (\PDOException $e) {
$exception_message = $e->getMessage();
if (
($this->shouldReconnect)
&& strpos($exception_message, 'server has gone away') !== false
&& $retry_attempt <= self::RETRY_ATTEMPTS
) {
$has_gone_away = true;
} else {
/*
* What are you going to do with it... Throw it back.. FIRE IN THE HOLE
*/
throw $e;
}
}
if ($has_gone_away) {
$retry_attempt++;
$this->reconnect();
goto try_again;
}
}
/**
* Connects to DB
*/
private function connect()
{
$this->db = new PDO($this->dsn, $this->username, $this->passwd, $this->options);
/*
* I am manually setting to catch error as exception so that the connection lost can be handled.
*/
$this->db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
/**
* Reconnects to DB
*/
private function reconnect()
{
$this->db = null;
$this->connect();
}
}
그런 다음 PDO에서처럼 위 클래스를 사용할 수 있습니다.
try {
$db = new ConnectionManagerPDO("mysql:host=localhost;dbname=dummy_test", "root", "");
$query = $db->query("select * from test");
$query->setFetchMode(PDO::FETCH_ASSOC);
}
catch(PDOException $e){
/*
handle the exception throw in ConnectionManagerPDO
*/
}
사용해보십시오.PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true)
팟 인스턴스로 설정합니다.도움이 될지는 모르겠지만 로그 데이터 없이 얻은 것은 그것뿐입니다.
연결이 끊어졌거나(예를 들어 wait_timeout 또는 KILL 명령을 실행하는 다른 스레드에 의해), 서버가 크래시되었거나 어떤 방식으로든 mysql 프로토콜을 위반했을 수 있습니다.
후자는 PDO의 버그일 가능성이 높으며 서버 측에서 준비된 스테이트먼트 또는 다중 결과(hint: Don't)를 사용하는 경우 매우 가능성이 높습니다.
서버의 크래시를 조사할 필요가 있습니다.서버 로그를 참조해 주세요.
그래도 무슨 일이 일어나고 있는지 모를 경우 네트워크 패킷덤퍼(tcpdump 등)를 사용하여 접속 내용을 덤프합니다.
일반 쿼리 로그를 활성화할 수도 있지만 프로덕션에서는 매우 신중하게 수행할 수 있습니다.
Nathan H, 아래는 pdo 재연결 + 코드 사용 샘플용 php 클래스입니다.스크린샷이 첨부되었습니다.
<?php
# set errors reporting level
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
# set pdo connection
include('db.connection.pdo.php');
/* # this is "db.connection.pdo.php" content
define('DB_HOST', 'localhost');
define('DB_NAME', '');
define('DB_USER', '');
define('DB_PWD', '');
define('DB_PREFIX', '');
define('DB_SHOW_ERRORS', 1);
# connect to db
try {
$dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PWD);
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
# echo $e->getMessage()."<br />";
# exit;
exit("Site is temporary unavailable."); #
}
*/
$reconnection = new PDOReconnection($dbh);
$reconnection->getTimeout();
echo $dbh->query('select 1')->fetchColumn();
echo PHP_EOL;
echo 'sleep 10 seconds..'.PHP_EOL;
sleep(10);
$dbh = $reconnection->checkConnection();
echo $dbh->query('select 1')->fetchColumn();
echo PHP_EOL;
echo 'sleep 35 seconds..'.PHP_EOL;
sleep(35);
$dbh = $reconnection->checkConnection();
echo $dbh->query('select 1')->fetchColumn();
echo PHP_EOL;
echo 'sleep 55 seconds..'.PHP_EOL;
sleep(55);
$dbh = $reconnection->checkConnection();
echo $dbh->query('select 1')->fetchColumn();
echo PHP_EOL;
echo 'sleep 300 seconds..'.PHP_EOL;
sleep(300);
$dbh = $reconnection->checkConnection();
echo $dbh->query('select 1')->fetchColumn();
echo PHP_EOL;
# *************************************************************************************************
# Class for PDO reconnection
class PDOReconnection
{
private $dbh;
# constructor
public function __construct($dbh)
{
$this->dbh = $dbh;
}
# *************************************************************************************************
# get mysql variable "wait_timeout" value
public function getTimeout()
{
$timeout = $this->dbh->query('show variables like "wait_timeout"')->fetch(); # print_r($timeout);
echo '========================'.PHP_EOL.'mysql variable "wait_timeout": '.$timeout['Value'].' seconds.'.PHP_EOL.'========================'.PHP_EOL;
}
# *************************************************************************************************
# check mysql connection
public function checkConnection()
{
try {
$this->dbh->query('select 1')->fetchColumn();
echo 'old connection works..'.PHP_EOL.'========================'.PHP_EOL;
} catch (PDOException $Exception) {
# echo 'there is no connection.'.PHP_EOL;
$this->dbh = $this->reconnect();
echo 'connection was lost, reconnect..'.PHP_EOL.'========================'.PHP_EOL;
}
return $this->dbh;
}
# *************************************************************************************************
# reconnect to mysql
public function reconnect()
{
$dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PWD);
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
}
# /Class for PDO reconnection
# *************************************************************************************************
오늘 아침에 Laravel에서 DB 속성을 변경한 후 동일한 오류가 발생했습니다.나는 오래된 설정을 코멘트하고 새 설정을 붙여 넣었다.는 새로운 이었다.DB_CONNECTION
★★★★
DB_CONNECTION=pgsql
sqlite, mysql 등 사용하고 있는 접속 유형을 추가해야 합니다.
나도 똑같은 문제가 있었어.PDO 개체를 NULL로 설정하지 않고 설정 해제하여 이 문제를 해결했습니다.
예를 들어 다음과 같습니다.
function connectdb($dsn,$username,$password,$driver_options) {
try {
$dbh = new PDO($dsn,$username,$password,$driver_options);
return $dbh;
}
catch(PDOException $e)
{
print "DB Error: ".$e->getMessage()."<br />";
die();
}
}
function closedb(&$dbh) {
unset($dbh); // use this line instead of $dbh = NULL;
}
또한 모든 PDO 개체의 설정을 해제하는 것이 좋습니다.여기에는 준비된 문장이 포함된 변수가 포함됩니다.
$pdo = new PDO(
$dsn,
$config['username'],
$config['password'],
array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
이거 먹어봐.될 수도 있다
언급URL : https://stackoverflow.com/questions/2232150/pdo-mysql-server-has-gone-away
'source' 카테고리의 다른 글
JSON JQ(기타 없는 경우) (0) | 2023.02.09 |
---|---|
PDO:: fetchAll vs. PDO:: 루프에서의 fetch (0) | 2023.02.01 |
Express를 사용하여 NodeJS 서버에서 파일 다운로드 (0) | 2023.02.01 |
어떻게 mysql에서 같은 테이블에 두 번 앉지? (0) | 2023.02.01 |
목록 이해에 있어서 if/inclused (0) | 2023.02.01 |