博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mysql表没有索引,并发的情况下导致CPU飙升
阅读量:4041 次
发布时间:2019-05-24

本文共 2166 字,大约阅读时间需要 7 分钟。

虽然mysql中的单表数据量不大,几万条,但是在并发事务(并发数100-200之间,瞬间抢坑位)控制下,导致CPU飙升,查询该表的select也耗时很久。

1、查看了mysql的CPU飙升时,IO、连接数、带宽、内存等监控指标都正常

再查看慢SQL,超过1秒的SQL没有。

再看表的设计,没有设计索引,将索引加上,同时mysql配置增加到16G的配置,问题得到解决。

虽然单条SQL执行效率快,但是没有索引的情况,在高并发的情况下,会出现抢占资源,因而导致CPU飙升。

最好是现场show processlist;查看线程具体情况,explain分析SQL执行情况,采用的哪个索引,进行优化SQL。

2、mysql不同的事务隔离级别,加锁的情况不一样,mysql的select都是快照查询没有锁的,除非指明 for update ,lock in share mode(其他事务不可修改)锁

已提交读(Read committed):没有加间隙锁

可重复读(Repeatable read):事务是有加间隙锁的

锁机制

(之所以以InnoDB为主介绍锁,是因为InnoDB支持事务,支持行锁和表锁用的比较多,Myisam不支持事务,只支持表锁)

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
  • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!。

--------这个是针对update没有索引的情况,行锁可能升级为表锁。

更多隔离跟锁介绍:

3、索引过滤性太差引起CPU飙高分析

有一点是经常被忽略的,那就是索引的过滤性。比如我们给一个整型字段加索引,而这个字段在几乎所有的记录上的值都是1(过滤性很差),那么我们通过这个索引来查找数据就会遍历大部分无关记录,造成浪费。

我们知道update语句也是通过索引来查找待更新的数据的,而且update会给索引查找的记录加上X锁,因此索引过滤性不好不但造成性能下降,还有可能造成锁争夺和锁等待的损耗。

我们看到耗CPU最高的调用函数栈是…mutex_spin_wait->ut_delay,属于锁等待的逻辑。InnoDB在这里用的是自旋锁,锁等待是通过调用ut_delay做空循环实现的,会消耗CPU

需要重点看一下:

4、数据库技术学习贴(非常值得学习)

阿里月报:

————————————————————————————————————————————————————

下面的摘录于

若id列上没有索引,SQL会走聚簇索引的全扫描进行过滤,由于过滤是由MySQL Server层面进行的。因此每条记录,无论是否满足条件,都会被加上X锁。但是,为了效率考量,MySQL做了优化,对于不满足条件的记录,会在判断后放锁,最终持有的,是满足条件的记录上的锁,但是不满足条件的记录上的加锁/放锁动作不会省略。同时,优化也违背了2PL的约束。

简单来说,mysql的死锁检测到之后,会选择一个事务进行回滚。而选择的依据:看哪个事务的权重最小,事务权重的计算方法:事务加的锁最少;事务写的日志最少;事务开启的时间最晚。实验1,事务2写了日志,事务1没有,回滚事务1。实验2,都没写日志,但是事务1开始的早,回滚事务2。

 

下面的摘录于

SQL语句中的where条件,使用以上的提取规则,最终都会被提取到Index Key (First Key & Last Key),Index Filter与Table Filter之中。

Index First Key,只是用来定位索引的起始范围,因此只在索引第一次Search Path(沿着索引B+树的根节点一直遍历,到索引正确的叶节点位置)时使用,一次判断即可;

Index Last Key,用来定位索引的终止范围,因此对于起始范围之后读到的每一条索引记录,均需要判断是否已经超过了Index Last Key的范围,若超过,则当前查询结束;

Index Filter,用于过滤索引查询范围中不满足查询条件的记录,因此对于索引范围中的每一条记录,均需要与Index Filter进行对比,若不满足Index Filter则直接丢弃,继续读取索引下一条记录;

Table Filter,则是最后一道where条件的防线,用于过滤通过前面索引的层层考验的记录,此时的记录已经满足了Index First Key与Index Last Key构成的范围,并且满足Index Filter的条件,回表读取了完整的记录,判断完整记录是否满足Table Filter中的查询条件,同样的,若不满足,跳过当前记录,继续读取索引的下一条记录,若满足,则返回记录,此记录满足了where的所有条件,可以返回给前端用户。

 

转载地址:http://yxadi.baihongyu.com/

你可能感兴趣的文章
在C++中使用Lua
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.147 - LeetCode1108
查看>>
No.174 - LeetCode1305 - 合并两个搜索树
查看>>
No.175 - LeetCode1306
查看>>
No.176 - LeetCode1309
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
mysql:sql alter database修改数据库字符集
查看>>
mysql:sql truncate (清除表数据)
查看>>
yuv to rgb 转换失败呀。天呀。谁来帮帮我呀。
查看>>
yuv420 format
查看>>