写了一个存储过程为玩家发送奖励,MySQL5.0
在本地测试语法没有问题,但在线上运行十分缓慢,show processlist ,status显示 sending data;可初步判断语句未使用索引。由于执行太慢,我们选择kill 掉了该语句。
设计到的语句部分:select ... from p join a ON p.pid=a.gameid=1428;explain type 显示 all 即全表扫描;(pid和gameid 都是含有索引的);按道理来说不应该是全表扫描,初步怀疑是利用索引的成本(CBO)太大,MySQL才选择了全表扫描;但这一的解释也是不合理的。pid和gameid都是唯一的。及表中索引的基数还是很大的。修改语句为:select ... from p join a ON p.pid=a.gameid and p.pid=1428; explain type显示为a表为all,p表为const;执行速度提高百倍。
小结:select查询共有3个过滤器,on、where、having,on是最先执行的过滤过程。应该讲多个条件依次写出,不要写出三个选项作为一个过滤条件,即不要出现:p.pid=a.gameid=1428 应该为p.pid=a.gameid and p.pid=1428(这个算不算MySQL 5.0的bug 呢?)
由于是多区多服DB批量执行该脚本。再次执行脚本的时候造成部分玩家收到双份奖励,这个可以通过临时表中进行记录,并及时更新到正确状态。关键是如何更好的更好的减少出错:
小结:对于线上更新语句,线上必须有足够多的数据进行测试;
批量执行过程遇到截断或停止(人为或突发情况),截断的时候要考虑到DBA是否能承受错误数据的压力;对于突发情况终止,进行操作行为记录,具体行为数据前后变化状态等。
本文转自 位鹏飞 51CTO博客,原文链接:http://blog.51cto.com/weipengfei/1192569,如需转载请自行联系原作者