Monday, June 27, 2011

PHP class x has no unserializer

I apologize for not having posted in quite a while, but I have been quite busy lately.  Writing lots of new code, developing a few new systems, trying to make everyone's lives better.  And, in doing that, I would like to post a rare problem on here, because this is one of the few problems I've had where Google was no help whatsoever.  Here goes:


Where I work, we use memcache to help make things a little bit faster.  For those who don't know, memcache is a daemon that basically accepts primitive data types (except anything equating to false) and keeps them in memory until they are needed again (written in C, very fast).  The PHP extension for memcache takes the data, serializes it (turns it into a string representation of whatever object you have given it), and stores it in memory (this post can also be my argument against using serialization wherever possible, especially for the lack of interoperability with other programming languages).  Recently, we have been getting an intermittent error when retrieving items out of the cache:

Warning:  Class Collection has no unserializer (Cache line 73)


Which a quick Google search returns almost nothing useful for.  A good friend and colleague of mine and I took to the memcache source code, and finally the PHP source code to try to find a solution.  There was certainly nothing obvious, except that the error is triggered when the object is unserialized (duh).  Also, we could not reproduce this error in our development environment (only in production).  But the only things we did know, was that it only happened on our 'Collection' class, and that it only happened in specific systems.  My incredibly keen colleague figured out that these systems were all part of the same zend cluster, which was one of our last clusters still on PHP 5.2 (we are in the process of upgrading).  I should also point out that our Collection class extends 'ArrayObject', a built in SPL class that is great for treating arrays as objects.  Well, as luck would have it, ArrayObject implements an interface in 5.3 that is not available in 5.2, called 'Serializeable'.  This interface allows customization of the serialize and unserialize functions.  The warning we were receiving occurred when a collection would be cached from a script running on a 5.3 server, and retrieved from a script running on a 5.2 server.  It seems like this should have been a fatal error, but apparently it doesn't because of the way the PHP source registers the custom serializations.

Anyways, the simple answer is to create a new memcache pool for our machines still on 5.2 separate from the 5.3 boxes.  The long term solution is finish the upgrade :)

Lesson here, be careful for problems that don't seem like they could stem from a version upgrade.  Also, always be wary of using serialize / unserialize for transporting data.  If you ever wanted to use a different language to parse the data, you would be pretty much SOL.  I recommend json_encode/decode wherever possible, because then you start thinking in the mindset of data, as opposed to specific language constructs.

Happy debugging

2 comments:

  1. Thank you. Your post helped me a lot. We have almost same situation in our company.

    ReplyDelete
  2. I'm very happy that this helped! Hopefully you were able to resolve it quickly. I want to continue sharing odds and ends on here in the hopes that someone can avoid a frustrating situation such as this one.

    ReplyDelete