记一次小失误导致的大事件,Mysql SQL Error: 0, SQLState: null 排查过程
本站一直依赖收录都是持续的。最近抽风了,一直没收录。一个星期就几十甚至没有,以前都是每天都有不少,有的时候一天几百上千。查看了接口平台。一堆错误。
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
SQL Error: 0, SQLState: null
全是SQL Error: 0, SQLState: null
错误。
开始排查
1.检查数据库
开始看了下 RDS 数据库。这里说明下,本站是有几个数据库的,几个 RDS ,年费用一万多。我看了下数据库的性能数据。
CPU是4
核的,但是都过度使用了,最大已经100%
了。我先排查下是不是接口暴露了,被人 DDOS 方式获取数据了?(因为之前有出现过类似事情)
查看了接口Nginx日志,排除了接口被攻击的可能性,通过sojson.com Nginx
只看到了大量的百度爬虫超时。
为了让百度爬虫爬到数据,我先把一个任务程序停了,然后把数据库重启了下,结果出现了新的异常,其实是属于一类。那么只能继续排查了。
Unable to acquire JDBC Connection
Unable to acquire JDBC Connection
Unable to acquire JDBC Connection
分析查看连接数和IOPS
都过度使用,应该是有执行SQL
占着链接没释放,一般是大查询和复杂查询,或者是有SQL
条件有问题,如搜索没带条件,导致全表查询,随即排除了这些问题。
随后把SQL
记录打开,然后锁定了一条SQL
。
//伪SQL
select xxxx from table where table.check_time= ?
条件是传了,我把这条 SQL 复制出来放到DataGrip
中执行一下,发现超时了,因为表很大,瞬间明白了,这个字段忘记加索引了。其实之前是有索引的,上次数据库被我家小黑客捣乱删除了表(120
万数据),后来恢复了。导致部分字段有后遗症。
对check_time增加索引后再看性能分析表:
发现恢复了。
总结经验
我项目是用的Springboot 2.x
,数据库是 Mysql ,连接池默认是 HikariPool
,我也尝试换成了原来的Springboot 1.x
的 druid 数据库连接池。结果没用,不是连接池的问题(其实主要是我对HikariPool
不熟悉,既然Springboot2.x
换成了HikariPool
,肯定是没问题的,只是我不熟悉,怕我配置有问题,所以换成了我一个稍微熟悉的来排查问题)。
排查问题点,着重找连接时间长,也就是占用着数据库连接不放回连接池的操作( SQL ),这样的SQL往往有几种。
1.常见的就是大数据查询(一次吞吐数据特别大)。
解决方案:
用多次查询代替、读写分离、分表等替代,或者增量查询结合NoSQL
处理。
2.复杂查询,复杂查询比如说各种函数统计、聚合、计算等等,或者是表关联特别多。
解决方案:
综合考虑业务,耦合度降低点,分析SQL
执行时间,对SQL
进行优化,适当加索引,关联多的情况下,先把大表条件检索完毕后再去Join
其他表,总之简化查询逻辑,或者加入 NoSQL 中间件处理。
3.高频查询,其实和第一次的效果差不多,就是导致连接数供不应求。
解决方案:
这个可以在数据库性能允许的情况下增加连接池链接。如果不能有效解决,综合考虑数据查询实时性、重复率等等适当加一些Cache
来解决,如果不能解决,还是考虑NoSQL
。如果是条件检索导致查询慢,可以尝试分析SQL
后添加对应影响性能的字段索引,增加读写分离,多实例读,或者分表,分表要注意尽量有业务逻辑的分表。比如按时间,按业务类型等等。
版权所属:SO JSON在线解析
原文地址:https://www.sojson.com/blog/341.html
转载时必须以链接形式注明原始出处及本声明。
如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。