由一次MySQL事故想到的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由一次MySQL事故想到的相关的知识,希望对你有一定的参考价值。

去年10月入职一家新公司,因公司内部某种不和谐因素造成上一个php程序员匆忙离职,相关工作都交接到我手里。

  前面说到内部有不和谐的因素存在,因此相关的项目代码也是敷衍了事质量不高,也就为后续事故埋下了炸弹。

  到了年底某天,客户的项目需要参加国家级某项评审,炸弹终于爆炸了。

  打开该项目,所有的普通用户皆能正常访问,唯独只有官方评选小组的专家无法访问。更可怕的所有的专家只用同一个账号,且我们对专家账号一无所知。
  
  客户炸了,急得不行了。连夜打电话到老板哪里,老板又半夜电话到了我。当晚,按照正常账号、正常业务流程走了一遍,没有发现任何问题。但是不知道专家账号,也不可能知道专家账号,问题无法排查自然也就留到次日。

  次日上午,火速前往客户单位机房,现场查询访问日志记录。

  顶着客户施加的强大的压力,冷静一下,终于找到专家账号留下的蛛丝马迹。于是,顺藤摸瓜就把问题根源找到并解决了。真惊险,差点小命不保,被客户喷死。

  问题的根源是评审专家的账号是“audit_expert”12位长度,普通用户都是手机号11为长度。再看一下数据表,发现账号字段account被设计成了varchar(11)。专家账号被存储为 “audit_exper”,写入数据库的时因长度限制被截断丢失了一位。

  怪不得专家打死都登录不上去。这悲催的专家,这傻x的数据表设计。于是,调整数据长度类型,手工修复专家账号。问题就解决了。
  
  技术图片

  那么问题来了,如何避免重要数据被截断,造成脏数据?

1.修改mysql的sql_mode中设置开启STRICT_TRANS_TABLES严格模式。
技术图片

2.表的存储引擎设置为innoDB。

3.程序脚本在对数据表写操作的时候,主动捕获错误异常并进行预警和处理。

演示

1.往test表中写入a-z长度为26的字符串单条数据,MySQL抛出错误信息:ERROR 1406 (22001): Data too long for column ‘name‘ at row 1。写入数据失败
技术图片

2.批量往test表中写入数据,test表存储引擎为innodb。发生错误会整理回滚。

技术图片

以上是关于由一次MySQL事故想到的的主要内容,如果未能解决你的问题,请参考以下文章

MySQL大无语事件:一次生产环境的死锁事故,看看我怎么排查

生活思考由一次修理门锁想到的

记录一次Mysql主从不同步事故问题于事故解决办法

回顾nacos的一次严重事故,节点意外全部离线

线程池运用不当的一次线上事故

恐怖!ThreadLocal引起的一次线上事故