目录
前言
一般的系统中,数据库往往都是性能瓶颈。在一个系统中,数据库被使用的频率很高,因为几乎所有的应用程序都需要与数据库交互来读取或写入数据。所以一旦数据库的响应慢,负载突增,则会大大影响系统的运行效率,严重点甚至可能直接崩溃。
面对数据库响应变慢,负载突增问题,应该及时处理,以下是处理的思路,依次考虑
- 减少查询
- SQL优化
- 索引优化
- 减少锁
- 避免大事务
- 扩容
- 硬件升级
解决方案
减少查询
减少查询时最优先考虑的优化步骤,具体的做法就是做一层缓存,每次请求优先从缓冲中读取,缓存中不存在数据再来查询数据库,这样能够有效地减少数据库查询的次数。
SQL优化
查询路径优化
使用limit提前终止查询
联表查询中使用小表驱动大表(实际上MySQL的查询优化器会自动优化)
查询语句优化
explain 检查查询语句是否走了索引
查询语句尽量做到索引覆盖,避免回表查询
索引下推:MySQL 5.7 的版本能在二级索引查询后先过滤再回表查询,减少了回表查询的次数
索引优化
如果索引列数据量过大,只要索引列值足够散列,则可以只截取前面部分做索引
创建联合索引,应当根据索引列值的散列程度由高到低从左到右排列创建,创建联合索引后,叶子节点数据按索引列排序。在查询的时候,根据最左匹配原则,优先匹配最左边散列度最高的列,由于散列度足够高,匹配到的数据最为精确,范围最小,所以遍历时用的时间也最少。
减少锁
MySQL事务的默认隔离级别为 RR(REPEATABLE READ 可重复读)
为了不可重复度问题和部分幻读问题,在 RR 隔离级别下,除了会加 Record Lock(记录锁)外,还会加 Gap Lock(间隙锁)和 Next-key Lock(临键锁),使用了间隙锁和临键锁,就会使得所得粒度变大,发生死锁的概率也变大,支撑不了高并发业务场景。
为了提高并发度,可以将MySQL的事务隔离级别降为 RC(READ COMMITTED 读已提交)
在 RC 隔离级别下,只会添加 Record Lock(记录锁),只会对要修改的当前行加锁,粒度相比间隙锁和临键锁小了很多,因此能够提升并发度和降低死锁概率。
如果将事务隔离级别修改成 RC,则需要自己去处理事务中的不可重复读问题。在 RC 级别中,每次读取都会得到最新的数据,所以很有可能读取到其他事务提交的修改。
避免大事务
并不是事务中执行的语句很多才叫大事务,而是指运行时间很长的事务。即使事务中只有一条执行语句,但是这条执行语句执行时间很长,它就是一个大事务
不用非索引列来更新数据,会锁全表
尽可能用主键索引列来更新数据。
由于使用非主键索引,锁住非主键索引后还需要回表去锁住主键索引叶子节点中的数据。
在某些情况下,会发生死锁。
事务1 事务2 执行结构 begin 锁住id=1的主键索引 success begin 锁住id=2的主键索引 success 锁住name=b的非主键索引
回表加锁id=2的主键索引
block 锁住name=b的非主键索引 dead lock
删除数据时需先检查数据是否存在,因为删除一个不存在的数据,扫描索引后发现不存在,会加上间隙锁。
扩容
在以上措施都做了之后还是没法将很好降低数据库负载,那么还可以采用读写分离的技术方案,为MySQL做一个主从复制,主库处理写请求,从库处理读请求,根据读请求的并发量进行水平扩容,增加从库的数量。
MySQL的主从复制,可以实现读写分离,以及读库的水平扩容,将读请求分散到多个数据库中,从而降低单个数据库的负载,非常适用于读多写少的业务场景
硬件升级
最后,就是升级数据库服务器了,没有什么是升级硬件解决不了的。早点升级服务器,少整一些有的没的优化,早点下班,反正是老板出钱。