公司运营项目迁移,这个项目最重要的就是充值和让玩家能玩游戏,还有后台统计,就是类似支付宝这样的第三方平台的支付工具,由于涉及的到钱,所以上个月就做好迁移的准备,将代码和数据库都已转移完毕,并提交运营那边测试,最后跟运营讨论说凌晨0点充值的人最少,开始切域名,考虑到切换DNS后无法立即生效,所以做了301跳转,整个迁移流程是:

1.暂停原服务器数据库,导出相关数据库

2.将导出的数据库同步到杭州xx服务器上面并导入到数据库中

3.切换域名指向到xx服务器

4.原服务器上面做301跳转到xx服务器(保证不写入新数据到原运营服务器上面)

5.运营协助测试新服务器数据是否正常

按照上面的流程操作,结果出现了很多意想不到的问题,因为这次迁移的LNMP环境不同,特别的是数据库,以前用的是Ver 14.14 Distrib 5.1.60,新服务器用的是Ver 14.14 Distrib 5.6.16,还有一个mysql的主辅同步,做了过滤,只同步了某些表,当时凌晨迁移,将最新的数据再次导入新服务器mysql,由于版本的问题,发现有个mysql存储过程无法导入,还有默认值问题,如下图:默认值要改为"NULL",不能是"无",原mysql中还有些定时任务无法导出,只能重新创建了。

一次网站迁移故障及分析_数据库同步

好了,解决了上面的问题,重新做了mysql主辅同步和过滤,当时测试也是正常的,结果第二天早上8点半用户流量过来了,网站都打不开了,首先查看了php日志,出现下面这个问题:

一次网站迁移故障及分析_迁移_02然后不断的修改下面的参数,感觉调到2048后已经是临界值了,因为这台机器只有8G内存,max_children = 2048后发现内存基本满了,在调高可能内存就爆了,当时调整php后发现可以短时间的正常访问,功能也正常,但是过了10分钟左右,又出现访问很慢的问题,继续看php日志,还是上图的提示,感觉这个不是php的问题,因为这个网站原服务器没有开启这么多php进程,但是运行正常,整个站的出口流量也不大。

一次网站迁移故障及分析_数据库同步_03

综上分析,发现应该是php连接mysql出现了堵塞,导致php进程一直在排队,当新的请求过来后,由于其他的php进程都在排队,只能在开启新的php进程,php进程永远提示繁忙,不够用,要调整max_children值,于是就看mysql是不是有问题?

进mysql,show processlist查看mysql的全部的线程,发现pay库里面有张uc_members表大量lock,

一次网站迁移故障及分析_php_04

大量的锁表,询问开发这张表是用户表,也就是用户每次登录都要查询这张表,这下终于找到原因了,就是php执行用户登录的时候,要读取mysql中这张uc_members表,每个用户登录都要锁表然后查询用户登录信息,导致这张表一直处于被锁死的状态,随着用户请求越来越多,php进程也增多,一直等待mysql返回用户登录信息,但是mysql一直处于锁表状态,结果就导致了这种现象,php进程卡死,用户无法登录,网站最后也打不开。

查看这张表用的是MyISAM的引擎:

一次网站迁移故障及分析_php_05


MyISAM引擎是表级锁,更换为InnoDB引擎为行级锁,再次show processlist发现锁表大量减少,页面可以正常打开,用户也可以登录了,问题解决。

InnoDBMyisam的六大区别:

一次网站迁移故障及分析_迁移_06

参考:http://www.ha97.com/4197.html


总结:

已经建议开发部门,以后开发程序不要再mysql里面写定时任务,因为mysql里面写定时任务,执行成功与否很难看到,迁移mysql的时候也会很麻烦,可以写crontab让php去执行定时任务即可,还有存储过程,如果一定需要在mysql里面写存储过程,尽量要规范,防止以后迁移由于mysql版本问题导致很多奇怪的现象。

出现这次故障主要是事先没有做压力测试,只是做了网站基本功能的测试,下次迁移网站之前一定要做好压力测试,用户登录测试及回滚方案,一个完整的迁移流程应该是:


1.暂停原服务器数据库,导出相关数据库

2.将导出的数据库同步到杭州xx服务器上面并导入到数据库中

3.对xx服务器进行压力测试及用户登录测试

4.回滚方案,出现问题及时回滚到原服务器,保证用户正常访问

5.切换域名指向到xx服务器

6.原服务器上面做301跳转到xx服务器(保证不写入新数据到原运营服务器上面)

7.运营协助测试新服务器数据是否正常