title: Error while sending STMT_PREPARE packet. PID=20615
body: <p><strong>EDIT</strong>: Adding DB::connection()->reconnect(); to the send method after retrieving emails from the session, alleviates the issue. So it appears that the DB is getting disconnected or there are too many connections or something.</p>
  
  <p>I believe I have an issue here with MySQL disconnecting on a production server. The server matches my local dev setup (using Homestead 2) and is Ubuntu, MySQL, Nginx and PHP-FPM.</p>
  
  <p>I am using Laravel 4.2 and I have created functionality to interface with a Mailchimp campaign, create a static segment and add emails based on filtered criteria to that segment to send an email.</p>
  
  <p>I was initially running a whereIn() method on a model to retrieve a collection of contacts that matched an array of emails, roughly 2600 emails were passed to whereIn() as the value.</p>
  
  <p>On my production server, I kept receiving the error (works flawlessly on the local dev setup):</p>
  
  <pre><code>Error while sending STMT_PREPARE packet. PID=20615
  </code></pre>
  
  <p>So, during my research I discovered that it could be related to max_allowed_packet in the MySQL config of the server, so I modified my.cnf and increased the value to 256M (on my local dev machine the value is 16M and is sufficient). This had no effect on the error.</p>
  
  <p>I decided to go ahead and rather than use whereIn(), as a test build a new collection adding each contact one by one but unfortunately I am still receiving the same error, even when using 1 email. This is the query that is failing in this instance:</p>
  
  <pre><code>select * from `contacts` where `contacts`.`deleted_at` is null and `email` = joebloggs@example.com limit 1
  </code></pre>
  
  <p>So this clearly points to some sort of misconfiguration on my production server, even though I have made sure that both my local environment and the production MySQL configs match exactly.</p>
  
  <p>So, in summary, my local environment works fine and executes the code with no issues but the production server returns the packet error.</p>
  
  <p>I'm now at a bit of a loss on how to proceed. Can anyone help at all, please?</p>
  
  <p>Here is the code that I am using to retrieve the records:</p>
  
  <pre><code>// send() method to filter results based on a set of search fields, probably should rename this to filter
  
  public function send($id)
  {
      $campaign = $this-&gt;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-&gt;contact-&gt;getContactEmails($haveAttended, $haveNotAttended, $account, $companyName, $industryType, $accountManager, $jobTitle, $contactEmail)-&gt;lists('email');
  
          // Create a new Mailchimp static segment and return its ID
          $segmentId = $this-&gt;createNewSegment(MailchimpWrapper::lists()-&gt;staticSegments('123456789'), $id);
  
          // Add the emails array generated above to the static segment in Mailchimp
          $this-&gt;addContactEmailsToSegment($contactEmails, $segmentId);
  
          // Retrieve all the emails that matched a subscriber in Mailchimp that were added to the static segment
          $emails = $this-&gt;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()-&gt;reconnect(); here this allieviates the issue
  
          $contacts = $this-&gt;contact-&gt;getContactEmails($haveAttended, $haveNotAttended, $account, $companyName, $industryType, $accountManager, $jobTitle, $contactEmail, $emails)-&gt;paginate(10)-&gt;appends([
              'have_attended'     =&gt; Input::get('have_attended'),
              'have_not_attended' =&gt; Input::get('have_not_attended'),
              'account'           =&gt; Input::get('account'),
              'industry_type'     =&gt; Input::get('industry_type'),
              'account_manager'   =&gt; Input::get('account_manager'),
              'job_title'         =&gt; Input::get('job_title'),
              'contact_email'     =&gt; Input::get('contact_email')
          ]);
      }
  
      $this-&gt;layout-&gt;content = View::make('admin.newsletters.send', compact('campaign', 'contacts'))-&gt;withErrors($this-&gt;errors);
  }
  </code></pre>
  
  <p>This is how I retrieve the Mailchimp campaign:</p>
  
  <pre><code>// getSavedCampaign() method which retrieves the Mailchimp campaign we will be attaching the filtered segment to
  
  public function getSavedCampaign($id)
  {
      $campaign = (object) MailchimpWrapper::campaigns()-&gt;getList(['campaign_id' =&gt; $id], 0, 1)['data'][0];
      $campaign-&gt;create_time = new Carbon($campaign-&gt;create_time);
      $campaign-&gt;send_time = new Carbon($campaign-&gt;send_time);
      $campaign-&gt;content_updated_time = new Carbon($campaign-&gt;content_updated_time);
  
      return $campaign;
  }
  </code></pre>
  
  <p>This is how I retrieve the contacts/contact emails from my contacts table based on the filtered results:</p>
  
  <pre><code>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-&gt;whereIn('email', $emails);
      }
      else
      {
          $query-&gt;orderBy('email', 'asc')
              -&gt;where('contactable', 0)
              -&gt;where('opt_out', 0)
              -&gt;where('email', '!=', DB::raw("concat('', email * 1)"));
  
          if ( ! empty($companyName[0]))
          {
              $query-&gt;whereHas('account', function($query) use ($companyName)
              {
                  $query-&gt;where('company_name', 'like', "%$companyName[0]%");
              });
          }
  
          if ( ! empty($account[0]))
          {
              $query-&gt;whereHas('account', function($query) use ($account)
              {
                  $query-&gt;whereIn('id', $account);
              });
          }
  
          if ( ! empty($accountManager[0]))
          {
              $query-&gt;whereHas('account', function($query) use ($accountManager)
              {
                  $query-&gt;whereHas('user', function($query) use ($accountManager)
                  {
                      $query-&gt;whereIn('id', $accountManager);
                  });
              });
          }
  
          if ( ! empty($industryType[0]))
          {
              $query-&gt;whereHas('account', function($query) use ($industryType)
              {
                  $query-&gt;whereHas('industryType', function($query) use ($industryType)
                  {
                      $query-&gt;whereIn('id', $industryType);
                  });
              });
          }
  
          if ( ! empty($haveAttended[0]) or ! empty($haveNotAttended[0]))
          {
              $query-&gt;join('delegates', 'contacts.id', '=', 'delegates.contact_id')
                  -&gt;join('delegate_event', 'delegates.id', '=', 'delegate_event.delegate_id')
                  -&gt;join('events', 'delegate_event.event_id', '=', 'events.id')
                  -&gt;join('courses', 'events.course_id', '=', 'courses.id');
          }
  
          if ( ! empty($haveAttended[0]))
          {
              $query-&gt;whereIn('courses.id', $haveAttended);
          }
  
          if ( ! empty($haveNotAttended[0]))
          {
              $query-&gt;whereNotIn('courses.id', $haveNotAttended);
          }
  
          if ( ! empty($jobTitle[0]))
          {
              $query-&gt;whereIn('contacts.job_title_id', $jobTitle);
          }
  
          if ( ! empty($contactEmail[0]))
          {
              $query-&gt;whereIn('contacts.id', $contactEmail);
          }
      }
  }
  </code></pre>
  
  <p>This is how I create the new Mailchimp segment:</p>
  
  <pre><code>public function createNewSegment($segments, $campaignId)
  {
      foreach ($segments as $key =&gt; $segment)
      {
          if ($segment['name'] == 'CREAM-' . $campaignId)
          {
              MailchimpWrapper::lists()-&gt;staticSegmentDel('123456789', $segment['id']);
          }
      }
  
      $segment = MailchimpWrapper::lists()-&gt;staticSegmentAdd('123456789', 'CREAM-' . $campaignId);
  
      return $segment['id'];
  }
  </code></pre>
  
  <p>This is how I add the emails retrieved to the created segment:</p>
  
  <pre><code>public function addContactEmailsToSegment($contactEmails, $segmentId)
  {
      $listEmails = $this-&gt;generateListEmails(Config::get('mailchimp::apikey'), '123456789', 'subscribed');
  
      $emails = $this-&gt;buildSegmentEmails($contactEmails, $listEmails);
  
      if ($emails)
      {
          $emailsChunk = array_chunk($emails, 1000);
  
          foreach ($emailsChunk as $emails)
          {
              MailchimpWrapper::lists()-&gt;staticSegmentMembersAdd('123456789', $segmentId, $emails);
          }
      }
  }
  </code></pre>
  
  <p>This is the function that retrieves all the emails/contacts that have matched subscribers in Mailchimp and have been added to the segment:</p>
  
  <pre><code>public function getSegmentEmails($apiKey, $listId, $status, $segmentId)
  {
      $conditions = '&amp;segment[saved_segment_id]=' . $segmentId;
  
      return $this-&gt;generateListEmails($apiKey, $listId, $status, $conditions);
  }
  </code></pre>
  
  <p>This is how the list emails are pulled from Mailchimp:</p>
  
  <pre><code>public function generateListEmails($apiKey, $listId, $status, $conditions = null)
  {
      $url = 'http://us5.api.mailchimp.com/export/1.0/list?apikey=' . $apiKey . '&amp;id=' . $listId . '&amp;status=' . $status;
  
      if ( ! is_null($conditions))
      {
          $url .= '&amp;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;
  }
  </code></pre>