A tool I built recently started running into an issue while utilizing PHP’s serialization functions. In a nutshell, the tool would take a blob of data, serialize it and store it into a single column in the database. when the data was needed it would retrieve the data, unserialize it and present it to the user.
The error I started seeing was:
unserialize() [<a href='function.unserialize'>function.unserialize</a>]: Error at offset 49098 of 49151 bytes
This error confused me. According to the serialization docs (http://us3.php.net/manual/en/function.serialize.php) and various online searches, the serialize and unserialize functions have no upper bounds on maximum amount of data that can go through these functions. Their only limitation is basically the amount of memory that your system has. Remember that serialize and unserialize both use a lot of memory depending on how big your data set is.
Realizing that serialize() has no upper bounds to work with – I investigated whether this was a memory problem. Well, it turned out not to be a memory problem. I was getting no out of memory errors and my web page still completed loading. It was just the serialization function failing.
This then let me to investigate the possibility that the input data being sent into the serialization function was bad, or corrupted.
The first thing I did was investigate the size of the data in the database. You can do this using the OCTET_LENGTH function in MySQL:
SELECT OCTECT_LENGTH( <column-name> ) FROM <table-name>;
I immediately found that as time went on the records were growing in size (as expected). The image below illustrates what I saw.
Further down the query, I saw the size of the records that were all failing. Each record that failed had the exact same size in their data. It was then that i realized that I had hit an upper bound in my database database column save.
The MySQL column type was BLOB. This has a max size of 65535 bytes (or approximately 64kb of data). In my particular use case I was getting over the 64kb range and needed a bigger data value in my DB.
To accomplish this I altered my MySQL column to be a MEDIUMBLOB. You can do this using the following command:
ALTER TABLE <table> MODIFY <column> MEDIUMBLOB
The MySQL docs for Alter Table can be found here: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
The reason why serialize was failing was because the input data being sent into the serialization function was truncated. Thus the serialization would fail based upon bad data. The truncation occurred when inserting a new record into the database that exceeded the max available column size.
BLOB and TEXT fields in MySQL are great and offer a lot of flexibility. However they do not fail on inserting a record with too much data, they silently truncate.