引语:线上运行的真实环境总是变幻莫测,明明你在本地测试的时候各种情况都是OK得不要不要的,也许你还在为自己某个地方炫酷的效果以及神奇的设计感到激动不已!但是,到线上以后,就偶尔会跟抽风一样,会有人跟你,这里出问题了,那里出问题了!我就纳闷了,怎么可能出问题呢?哈哈,这也许就是大多数攻城狮们最经常发出的感叹吧!
那么,今天我们就来聊聊怎样发现你的错误以及解决一些错误的快速定位方法,而不是等到用户来你这里反馈,因为那时候可能已经错太久了!我们要做的,应该是将错误发现在第一时间,解决在萌芽之中,作出事后总结以避免以后再犯类似错误!因为,错不可怕,可怕的是一直犯同样的错误,那样的话,你和新手有何差别?
说明几点:
1. 本文主要解决问题的SQL相关的错误;
2. 本文以PHP微视角出发;(妈蛋,谁叫我是从事PHP开发呢?)
3. 本文解决的问题为,一、如何发现问题;二、如何解决问题;
4. 欢迎质疑、补充;
正题一、如何发现问题?
测试什么的那就不用说了,谁TM敢不过测试就直接上线?如果真是那样,我只能说,你牛逼!测试是一道很重要的防线保障,一般来说,经过测试后的功能,上线之后,Bug不会太多,或者说不会太明显!好吧,我就假设测试一个问题都没有发现,那么, 我们就上线吧!其实,上线之后,我们心里是没有底的,尤其是在某些还没有一套完善的部署系统的时候,上线前和上线后总会出各种稀奇古怪。到底开发和用户是两个层面的人,鬼知道会发生什么呢?我们悬着的一颗心,竟然要完全依赖于用户的操作,用户的反馈?噢,不,那样,太被动了!
主动发现问题。 一、上线之后,你也不可能再进行测试了,你现在就是一个普通用户,那么,你自己去操作就是必须的,一个大概走下来,基本功能可以确定了,Ok,接下来,真正交给用户! 二、如果没有后手,就真的完全交给用户,那你还是太Low了,因为,必要的监控措施是一定要有的!这里指的监控是程序级别的,也就是所谓的报错。怎样记录报错信息?怎样知道报错了?都说了嘛,我是从事PHP开发的。PHP中有一个记录错误日志的功能,error_reporting,把这个给打开,指定错误日志位置,级别,就可以记录PHP的错误了,但是一定要关闭错误的页面显示,否则,用户看到此类错误,你就完蛋了!既然本文说的是SQL错误,那不应该是这里,没错。但是我要说的是,当SQL报错的时候,PHP也已经发出报错了,通常是一个警告级别的错误,而且这种错误往往是关联性的发生,如下面的语句依赖于上面的查询,而上面已经报错,那么后续也会跟着报错。PHP知道错误了,但是只是大概,那SQL具体哪里错了?只有他自己知道,这种记录就交给他吧!大概原理就是,在查询出错的地方,记录错误日志,错误日志主要记录信息有:错误信息,文件位置(追根溯源一个个文件查上去直到入口),下面是一段示例记录错误信息的PHP代码供参考:
<?php // 记录sql错误日志 private function logError($msg = "") { if (isset($this->_logfile)) { if (!$msg) { if (!mysql_errno()) { return; } $msg = "mysql_errno: " . mysql_errno() . "\nmysql_error: " . mysql_error(); } file_put_contents($this->_logfile, ‘[‘ . date(‘Y-m-d H:i:s‘) . "] $msg\n", FILE_APPEND); $trace = debug_backtrace(); foreach ($trace as $call) { if(empty($call[‘file‘]) && empty($call[‘line‘])) { continue; } file_put_contents($this->_logfile, "{$call[‘file‘]} on line {$call[‘line‘]}\n", FILE_APPEND); } file_put_contents($this->_logfile, "\n", FILE_APPEND); } }
这样,你就有了一个可供参考的东西了,到时更改的时候,你只需去查看这个文件指示的地方,你就大概知道是什么错了,都知道什么错了,我想,要想解决问题,应该只是个时间问题了,而且是个短时间问题!
正题二、如何解决问题?
其实前面我已经说了,既然已经找到问题根源了,要解决问题只是个短时间问题,但是,我还是将给出一些解决方案作参考,毕竟,大家都这么忙,哪有时间破解你那烂代码!如下是一经常会出现的错误:
1. 报错:[2002] 由于目标计算机积极拒绝,无法连接。解析:数据库连接信息错误,你可能把测试环境连接部署到线上去了,这问题大发了,赶紧恢复吧? 附注:如果没有报错是因为你线上机器可以连接测试库,那问题也大发了;
2. 报错:[1146] Table ‘bbbq‘ doesn‘t exist。解析:表不存在,赶紧查查,是不是本次新加的表没有被添加到线上吧,或者表名写错了? 附注:一般过了测试的不太可能是表名写错了!
3. 报错:[1054] Unknown column ‘column_x‘ in ‘field list‘。解析:指定的列不存在,要么库中没有,要么写错了,赶紧查! 附注: 同上。
4. 报错:[1366] Incorrect string value: ‘\xA9\x96‘ for column ‘x_name‘ at row 1。解析:字符集问题,如一个gbk的字被字段设置为gb2312接收则会出现此问题,赶紧改回来吧!附注:请尽量使用utf-8编码,代码与入库都方便!
5. 报错:[1364] Field ‘pid‘ doesn‘t have a default value。解析:指定字段没有默认值,请确认应该获取到的值是否未获取从而为null,为某些不必要字段指定数据库默认值。 附注: 如有索引关系,请一定设置not null 选项,否则索引将可能失效!
6. 报错:[1366] Incorrect integer value: ‘‘ for column ‘townId‘ at row 1。解析:给定的值不符合字段类型要求,在入库之前先确认该字段需要什么类型,可做相应强制转换,再入库。 附注:某些版本的mysql可以自行强制转换类型处理此问题,但是结果可能已经超出你的预期!
...
等等,还要养家糊口,赶着去上班,稍后补充!后续问题关键字提示:LOAD DATA INFILE, REPLACE ...