【踩坑记录】记一次MySQL主从复制延迟的坑

最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯一样的错误。mysql

情景

一个活动信息须要审批,审批以后才能生效。由于以后活动要编辑,编辑后也可能触发审批,审批中展现的是编辑前的活动内容,考虑到字段比较多,也要保存审批活动的内容,所以设计采用了一张临时表,审批中的活动写进审批表(activity_tmp),审批经过以后才把真正的活动内容写进活动表(activity)。表的简要设计以下,这里将活动内容字段合并为content展现:sql

activity_tmp()
id
status // 审批状态    
content //  审批阶段提交的活动内容

activity
id
content // 审批经过后真正展现的活动内容

遇到的问题

当时是有编辑触发审批的状况,发现审批经过以后活动内容是空的,因而开始追查问题的缘由。这里说一句,当程序出问题的时候,95%都是代码的问题,先不要去怀疑环境出问题。好好的查日志,而后看看你的代码吧。数据库

追查问题回溯

一、查activity_tmp表,发现当时提交审批的活动内容是正常的,并且状态也更新为审批经过了,怀疑是写入activity表失败
二、查activity表,发现审批后的内容确实没有写入,怀疑是代码问题
三、查看代码,代码逻辑没看出问题,怀疑数据库操做失败,查看日志
四、日志显示,有一句insert语句的活动内容为空,活动内容来自上一个mysql执行的是select语句,把该select语句拿出来放到线上的备库查询,发现活动内容是存在的。运行时查询为空,执行完毕后查询时内容存在,初步怀疑是主从延迟问题。
五、报错只是部分失败,肯定是主从延迟的问题。架构

当时的问题代码

$intStatus = $arrInput[‘status’];
$this->objActTmp->updateInfoByAId($intActId, $intStatus);
// 更新后,立刻查
$arrActContent = $this->objActTmp->getActByStatus($intStatus);

这就是主从延迟出现的地方,update后,立刻get,这是主从复制架构上开发的一个大忌。学习

解决方案

这类问题的解决方案有两种:this

  • 修改代码逻辑spa

  • 修改系统架构设计

对于修改代码逻辑,鄙人有两点看法:日志

  • 若是第二步获取的数据不须要第一步更新的status字段,那就先读,而后再更新code

  • 若是第二步获取的数据须要依赖第一步的status字段,那就在读出来的时候先判断是否为空,若是是空的,报错,下一次重试。

总结

其实以前也听到过这样的例子,可是因为没有亲身经历,因此只保留了一种理论上的记忆,实际上印象不深,经历了这么一次踩坑后,印象特别深入,如今看到别人写这样的代码也能立刻发现并指出。仍是本身亲身去踩坑印象最深。

日志很重要,详细的日志更重要。日志要记录有用的信息,方便追查问题的时候去追溯问题的本质缘由。我以为日志就应该尽可能作成飞机中的黑匣子,帮助咱们保存“事故“发生时的全部相关信息。

接下来,会去学习主从复制的原理,敬请期待。

更多精彩内容,请关注我的公众号。

图片描述