PHP已經(jīng)出到了5.3.8穩(wěn)定版本,于是乎準(zhǔn)備將公司生產(chǎn)服務(wù)器上的PHP從5.2.17升級(jí)到5.3.8,在測(cè)試服務(wù)器上調(diào)試的時(shí)候卻發(fā)現(xiàn)了一個(gè)詭異的問題:
把PHP環(huán)境裝好后,原先能在5.2.17正常運(yùn)行的代碼報(bào)錯(cuò)了,提示PHP class x has no unserializer,而同一套代碼在同服務(wù)器上使用5.3.8則沒有任何問題.Google一下了發(fā)現(xiàn)沒有什么有用的信息,看來我是遇到冷門問題了,于是開始逐步debug檢查,發(fā)現(xiàn)報(bào)錯(cuò)的地方位于使用memcache取數(shù)據(jù)的部分,在取出緩存在memcache中的數(shù)據(jù)時(shí)提示我的類沒有反序列化功能,而此行代碼運(yùn)行在5.3.8的時(shí)候卻沒有任何問題.
鑒于唯一的線索是這個(gè)反序列化的提示了,搜索了一下php官方相關(guān)序列化的信息,首先找到了序列化接口Serializable的介紹,在這里我注意到該接口有一個(gè)unserializ方法,這個(gè)是用于反序列化類時(shí)調(diào)用的借口. 同時(shí),php的memcache擴(kuò)展在把php數(shù)據(jù)對(duì)象存到memcache時(shí)是會(huì)將其序列化的,難道是我自己使用的對(duì)象沒有實(shí)現(xiàn)Serializable接口的問題?追查了一下代碼發(fā)現(xiàn)我存在memcache中的類是繼承于Array_Object類,于是乎跑到官方Array_Object的介紹頁面一看,果然如此.
Array_Object從5.3.0開始就實(shí)現(xiàn)了Serializable接口,而5.2是沒有實(shí)現(xiàn)的。到這里,這個(gè)問題的原因也就明朗了,分析如下:
程序在兩個(gè)版本的PHP下運(yùn)行卻使用同一個(gè)memcache緩存池,我先測(cè)試的是5.3.8版本,那么存進(jìn)去的是PHP5.3的Array_Object對(duì)象,該對(duì)象在5.3下面可以正常序列化和反序列化,后來我又去訪問了運(yùn)行在PHP5.2下面的程序,這是在memcache中已經(jīng)有了緩存對(duì)象,所以5.2讀出來的是5.3中序列化的Array_Object對(duì)象,而在5.2中Array_Object是沒有實(shí)現(xiàn)Serializable接口的,那么在反序列化時(shí)就會(huì)出現(xiàn)錯(cuò)誤,也是就是提示PHP class x has no unserializer的原因。
解決這個(gè)問題的方法很簡(jiǎn)單,給每個(gè)程序使用不同的緩存池,避免產(chǎn)生數(shù)據(jù)污染和版本兼容問題。