当你的程序依赖于 MySQL 查询缓存…

前两天升级和迁移了一个 MySQL 环境,因为:

  1. 某天我发现原来的环境居然是个 RAID 0,尽管已经有个 Slave 环境了,但是把数据放在毫无冗余的磁盘上面实在是有太大风险。
  2. 系统需要扩展了,接手这个项目时候,程序和数据库都在一个机器,从性能、安全各个方面来说都不是很好的方案。
  3. MySQL 5.6 相比 5.5 在查询优化上面有很大的提升。
  4. 事实上刚好还有个 mongodb 需要升级版本,可以一起下线后升级。

OK,于是就找了个凌晨,下线、升级了,初看起来一切正常。

但是到了第二天,问题出现了。开发说从 MySQL 同步数据到 mongodb 非常慢,只有原来的 1/36!

于是都开始怀疑是 mongodb 的问题,难道是程序逻辑有问题?写新版本的 mongodb 没有对参数什么的?但是得到否定的答复。

。。。。。。

折腾了好一会儿,看了 mongodb 的各种文档之后,看了一下一直在跑着的 mongostat 输出,发现是有出现过高并发的写入(但不是出现问题的同步造成的),至少,这说明了——mongodb 升级后的写入功能本身是没有问题,事实上,观察到的结果是有提升。排除了 mongodb 的问题,心想是否可能 MySQL 的数据库问题,看了一眼慢日志,结果确实发现有大量的同一个超过 1s 的查询,时间点和同步一致。

问了一下开发,他们说这个查询应该会被缓存住,第一下很慢,但是后面就很快了!好吧,我看了一眼 MySQL 的查询缓存:

mysql> show status like 'Qcache%';

哈!全部是0,查询缓存被关闭了!

再查了一下 MySQL 的参考文档

query_cache_type
...
This variable defaults to OFF as of MySQL 5.6.8, ON before that.

MySQL 在 5.6 之前的版本是默认开启查询缓存的,而 5.6 开始却默认关闭了它!

于是,设置 query_cache_type=1 之后,重启 MySQL,同步一切正常了。

总结:MySQL 做了这个改动,但是却没有在它们的升级文档中给出说明;开发把程序一个重要的功能依赖于这个数据库缓存,也没有说明。谢谢你们一起给我出了难题!当然,更重要的一个事情是——升级之前没有彻底的测试过!!!所有人都想当然了,这是流程规范的问题。