标题好长。
今天整理数据发现06年之前我的博客数据还在,都有备份,所以打算都导入到现在的博客里。
在操作的过程中,用phpmyadmin导出数据库做了备份,当时导出选择的GZIP压缩,导出以后也没注意导出的文件是否正常。在我清理了数据库,打算重新导入的时候,悲剧发生了!MYSQL报错,经查看是导出的sql.gz文件有问题,用rar都不能打开!
服务器清空了,备份文件损坏。老话说的好,生命可贵,数据无价。对于一个程序员,这是天下最悲惨的事。在脑中浮现了N个脏话之后,怀着悲惨的心情,开始了慢慢的数据修复之路。任重而道远啊。
- 先确定问题发生原因。因为是导入时MYSQL报错#1064,自然的以为是SQL语句有问题。想查看SQL语句,发现备份文件打不开。当时还没想到是文件有问题,还以为是非标准GZIP压缩,不能被压缩软件识别,所以开始分析phpmyadmin代码,想看看这个GZIP文件是如何生成的,如何解压。但是phpmyadmin代码太庞大,嵌套模块太多,读起来很浪费时间,所以尝试了一下放弃,换用另一思路。考虑是否因为MYSQL和phpmyadmin版本兼容性问题,所以先尝试替换MYSQL版本,从5.1最早版本到5.7最新版本,挑了几个尝试,都未果,于是尝试替换phpmyadmin版本。在替换了几个版本也都失败以后,忽然发现新版的phpmyadmin导出的数据用winrar能打开,而我之前的打不开!恍然大悟,原来真是导出的数据出了问题!也就是说,是phpmyadmin本身的问题了。查看phpmyadmin更新文档,在4.4.9更新日志里看见“- bug #4942 Export to gzip saves plain text under Chrome”。这这句话有两个重点,一是说明4.4.9修复BUG了,二是说明这个BUG只在chrome浏览器下存在。为了进一步确认,分别用4.4.8和4.4.9测试了一下,结果IE下都正常,chrome下8导出异常9导出正常。好了,下一步拿出BC,对比一下两个版本源码,看看修改了什么地方,在“libraries\core.lib.php”发现一段代码
$notChromeOrLessThan43 = PMA_USR_BROWSER_AGENT != 'CHROME' // see bug #4942
这是.9版修复的,看出来了吧,这个补丁只针对chrome43以后版本,作用就是不输出HTTP头GZIP。再对比两个版本导出的数据,发现数据的后半部分是一样的,区别只在前半部分,就是.8导出的数据前面一部分是解压以后的,而.9的都是压缩的。
|| (PMA_USR_BROWSER_AGENT == 'CHROME' && PMA_USR_BROWSER_VER < 43);
if (strpos($mimetype, 'gzip') !== false && $notChromeOrLessThan43) {
header('Content-Encoding: gzip');
} - 找到问题原因,开始尝试修复。这里走了很多弯路,因为在分析数据时受到了很多误导,结果干了一宿一天。苦逼的过程自不必细说,那些成天查异常的兄弟们肯定都深有体会,只说结果吧。不说看似山,说了隔层纸,其实很简单:GZIP文件并不是整体压缩,而是分成一个一个数据块压缩并拼接起来的,输出损坏的数据,单纯是因为chrome在下载文件时,把第一个数据块解压了。后面的数据块并没有东,没有损坏。这样就简单了,把解压的那部分数据剪出来,通过GZIP算法压缩,在粘回去,压缩包就修复好了。
- 手工操作代码数据比较麻烦,所以写了个PHP小程序代劳,这里分享给大家。
文章评论
“$i = 0x130d6; //定位“1F 8B 08 00”” 这个变量,是否要自己从需要修复的文件中找出来?
@摩凝 竟然真有人搜索过来,那我详细说说修复文件用法吧。
用16进制编辑器打开待修复的数据文件,搜索代码“1F 8B 08 00”第一次出现的位置,把$i这个变量的值改成搜到的位置,然后在$fi变量定义待修复文件名,$fo定义输出文件名,在WEB页执行这个PHP,处理完毕。