Ошибка при отправке пакета STMT_PREPARE. PID = 20615

РЕДАКТИРОВАТЬ: Добавление DB :: connection () -> reconnect (); метод отправки после получения электронных писем из сеанса, устраняет проблему. Похоже, что БД отключается или слишком много подключений или что-то в этом роде.

Я считаю, что у меня есть проблема с отключением MySQL на производственном сервере. Сервер соответствует моей локальной настройке dev (используя Homestead 2) и является Ubuntu, MySQL, Nginx и PHP-FPM.

Я использую Laravel 4.2 и создал функциональные возможности для взаимодействия с кампанией Mailchimp, создания статического сегмента и добавления электронных писем на основе отфильтрованных критериев в этот сегмент для отправки электронной почты.

Первоначально я запускал метод whereIn () для модели, чтобы получить коллекцию контактов, которые соответствовали массиву электронных писем, примерно 2600 электронных писем было передано whereIn () в качестве значения.

На моем рабочем сервере я продолжал получать сообщение об ошибке (безупречно работает при локальной настройке dev):

Error while sending STMT_PREPARE packet. PID=20615

Итак, во время моего исследования я обнаружил, что это может быть связано с max_allowed_packet в конфигурации MySQL сервера, поэтому я изменил my.cnf и увеличил значение до 256M (на моей локальной машине разработчика значение 16M и достаточно). Это не повлияло на ошибку.

Я решил пойти дальше, и вместо того, чтобы использовать whereIn (), в качестве теста создайте новую коллекцию, добавляя каждый контакт один за другим, но, к сожалению, я все еще получаю ту же ошибку, даже при использовании одного электронного письма. Это запрос, который не выполняется в этом случае:

select * from `contacts` where `contacts`.`deleted_at` is null and `email` = [email protected] limit 1

Так что это явно указывает на какую-то неверную конфигурацию на моем производственном сервере, хотя я убедился, что и моя локальная среда, и производственные конфигурации MySQL точно совпадают.

Итак, в общем, моя локальная среда работает нормально и выполняет код без проблем, но рабочий сервер возвращает ошибку пакета.

Я сейчас немного растерялся, как поступить. Кто-нибудь может помочь, пожалуйста?

Вот код, который я использую для получения записей:

// send() method to filter results based on a set of search fields, probably should rename this to filter

public function send($id)
{
$campaign = $this->getSavedCampaign($id);
$haveAttended = explode(',', Input::get('have_attended'));
$haveNotAttended = explode(',', Input::get('have_not_attended'));
$account = explode(',', Input::get('account'));
$companyName = explode(',', Input::get('company_name'));
$industryType = explode(',', Input::get('industry_type'));
$accountManager = explode(',', Input::get('account_manager'));
$jobTitle = explode(',', Input::get('job_title'));
$contactEmail = explode(',', Input::get('contact_email'));

// Check if there has been a POST request and if so get the filtered contact emails and add them to the session
if (Request::method() == 'POST')
{
// Retrieve an array of contact emails based on the filters supplied
$contactEmails = $this->contact->getContactEmails($haveAttended, $haveNotAttended, $account, $companyName, $industryType, $accountManager, $jobTitle, $contactEmail)->lists('email');

// Create a new Mailchimp static segment and return its ID
$segmentId = $this->createNewSegment(MailchimpWrapper::lists()->staticSegments('123456789'), $id);

// Add the emails array generated above to the static segment in Mailchimp
$this->addContactEmailsToSegment($contactEmails, $segmentId);

// Retrieve all the emails that matched a subscriber in Mailchimp that were added to the static segment
$emails = $this->getSegmentEmails(Config::get('mailchimp::apikey'), '123456789', 'subscribed', $segmentId);

// Put the emails array and the segment id in to the session
Session::put('emails', $emails);
Session::put('segmentId', $segmentId);
}

// Check if the session contains an array of emails and if so retrieve them and pull back an eloquent collection of contacts that match the emails stored in the session
if (Session::get('emails'))
{
$emails = Session::get('emails');

// EDIT: If I add DB::connection()->reconnect(); here this allieviates the issue

$contacts = $this->contact->getContactEmails($haveAttended, $haveNotAttended, $account, $companyName, $industryType, $accountManager, $jobTitle, $contactEmail, $emails)->paginate(10)->appends([
'have_attended'     => Input::get('have_attended'),
'have_not_attended' => Input::get('have_not_attended'),
'account'           => Input::get('account'),
'industry_type'     => Input::get('industry_type'),
'account_manager'   => Input::get('account_manager'),
'job_title'         => Input::get('job_title'),
'contact_email'     => Input::get('contact_email')
]);
}

$this->layout->content = View::make('admin.newsletters.send', compact('campaign', 'contacts'))->withErrors($this->errors);
}

Вот как я получаю кампанию Mailchimp:

// getSavedCampaign() method which retrieves the Mailchimp campaign we will be attaching the filtered segment to

public function getSavedCampaign($id)
{
$campaign = (object) MailchimpWrapper::campaigns()->getList(['campaign_id' => $id], 0, 1)['data'][0];
$campaign->create_time = new Carbon($campaign->create_time);
$campaign->send_time = new Carbon($campaign->send_time);
$campaign->content_updated_time = new Carbon($campaign->content_updated_time);

return $campaign;
}

Вот как я получаю контакты / электронные письма из таблицы контактов на основе отфильтрованных результатов:

public function scopeGetContactEmails($query, $haveAttended, $haveNotAttended, $account, $companyName, $industryType, $accountManager, $jobTitle, $contactEmail, $emails = null)
{
// If the emails session variable exists (is not null) simply run a whereIn query on the contacts table to retrieve all contacts that match an email in the array, otherwise run the filters
if ( ! is_null($emails))
{
$query->whereIn('email', $emails);
}
else
{
$query->orderBy('email', 'asc')
->where('contactable', 0)
->where('opt_out', 0)
->where('email', '!=', DB::raw("concat('', email * 1)"));

if ( ! empty($companyName[0]))
{
$query->whereHas('account', function($query) use ($companyName)
{
$query->where('company_name', 'like', "%$companyName[0]%");
});
}

if ( ! empty($account[0]))
{
$query->whereHas('account', function($query) use ($account)
{
$query->whereIn('id', $account);
});
}

if ( ! empty($accountManager[0]))
{
$query->whereHas('account', function($query) use ($accountManager)
{
$query->whereHas('user', function($query) use ($accountManager)
{
$query->whereIn('id', $accountManager);
});
});
}

if ( ! empty($industryType[0]))
{
$query->whereHas('account', function($query) use ($industryType)
{
$query->whereHas('industryType', function($query) use ($industryType)
{
$query->whereIn('id', $industryType);
});
});
}

if ( ! empty($haveAttended[0]) or ! empty($haveNotAttended[0]))
{
$query->join('delegates', 'contacts.id', '=', 'delegates.contact_id')
->join('delegate_event', 'delegates.id', '=', 'delegate_event.delegate_id')
->join('events', 'delegate_event.event_id', '=', 'events.id')
->join('courses', 'events.course_id', '=', 'courses.id');
}

if ( ! empty($haveAttended[0]))
{
$query->whereIn('courses.id', $haveAttended);
}

if ( ! empty($haveNotAttended[0]))
{
$query->whereNotIn('courses.id', $haveNotAttended);
}

if ( ! empty($jobTitle[0]))
{
$query->whereIn('contacts.job_title_id', $jobTitle);
}

if ( ! empty($contactEmail[0]))
{
$query->whereIn('contacts.id', $contactEmail);
}
}
}

Вот как я создаю новый сегмент Mailchimp:

public function createNewSegment($segments, $campaignId)
{
foreach ($segments as $key => $segment)
{
if ($segment['name'] == 'CREAM-' . $campaignId)
{
MailchimpWrapper::lists()->staticSegmentDel('123456789', $segment['id']);
}
}

$segment = MailchimpWrapper::lists()->staticSegmentAdd('123456789', 'CREAM-' . $campaignId);

return $segment['id'];
}

Вот как я добавляю электронные письма, полученные в созданный сегмент:

public function addContactEmailsToSegment($contactEmails, $segmentId)
{
$listEmails = $this->generateListEmails(Config::get('mailchimp::apikey'), '123456789', 'subscribed');

$emails = $this->buildSegmentEmails($contactEmails, $listEmails);

if ($emails)
{
$emailsChunk = array_chunk($emails, 1000);

foreach ($emailsChunk as $emails)
{
MailchimpWrapper::lists()->staticSegmentMembersAdd('123456789', $segmentId, $emails);
}
}
}

Это функция, которая извлекает все электронные письма / контакты, которые соответствуют подписчикам в Mailchimp и были добавлены в сегмент:

public function getSegmentEmails($apiKey, $listId, $status, $segmentId)
{
$conditions = '&segment[saved_segment_id]=' . $segmentId;

return $this->generateListEmails($apiKey, $listId, $status, $conditions);
}

Вот как списочные письма извлекаются из Mailchimp:

public function generateListEmails($apiKey, $listId, $status, $conditions = null)
{
$url = 'http://us5.api.mailchimp.com/export/1.0/list?apikey=' . $apiKey . '&id=' . $listId . '&status=' . $status;

if ( ! is_null($conditions))
{
$url .= '&segement[match]=all' . $conditions;
}

$handle = @fopen($url, 'r');
$chunk_size = 4096;
$i = 0;
$header = [];

while ( ! feof($handle))
{
$buffer = fgets($handle, $chunk_size);

if (trim($buffer) != '')
{
$obj = json_decode($buffer);
$listEmails[$obj[0]] = $obj[0];
$i++;
}
}

fclose($handle);

unset($listEmails['Email Address']);

return $listEmails;
}

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]