为什么mysql有时占用cpu很高

  在某些还不算高并发的场景下,为什么mysql服务器的cpu使用率会飙的很高,但是磁盘IO和网络IO的量却没有很大呢?这个和mysql的死锁检测机制有关系了。

 Innodb引擎是支持行锁的,在一个事务中,如果对某一行加了锁后想释放掉锁,需要等到提交事务后才会释放,是不能立刻释放的。

  假设在某个秒杀场景下,用户下单后需要对秒杀商品进行减库存的操作,为了防止超卖,就需要对库存加行锁,这个操作本身其实是不消耗cpu的,但mysql默认是开启死锁检测机制的,就导致每个加锁的线程都要判断,自己的加入是否会导致死锁,时间复杂度是O(n)。如果有一万个线程并发访问,死锁检测就是一亿的量级,会消耗大量的cpu资源,这就是我们看到cpu升高的主要原因。那么如何解决这个问题呢?

  mysql通过innodb_deadlock_on来控制是否开启死锁检测,通过innodb_lock_wait_timeout来控制超时时间。一种方法是关闭死锁检测,或将超时时间降低。如果项目已经上线,这是一种临时的解决方案,但如果其他的业务存在死锁,关闭死锁检测就可能会影响业务的正常运行。如果我们的业务是一个大事务,本身没有死锁,但是耗时确实比较久,降低超时时间的方式可能会误杀了正常运行的事务。

还有一种方法,是将加锁的行进行拆分,也就是库存拆分成100行,这样就通过增加业务复杂度的方式,降低了死锁检测的cpu消耗。这是比较常用的方式。当然之前最好对加锁的线程进行限流,否则简单的拆分库存可能也扛不住瞬时的并发量。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容