mysql问题排查

生产环境mysql服务器cpu100%,排查过程,后续优化思路

1、top命令查看cpu占用情况

2、执行 mysql -u root -p 进入mysql, 查看正在执行的sql

show processlist; //显示的sql不完整

show full processlist;

看到有多条相同的sql在查询,耗时较久

按照查询次数排序,导出前30条慢sql

mysqldumpslow -s c -t 30  /home/slow-20221002.log

主要参数:

A: -s, 是sort的意思,表示按照何种方式排序,c、t、l、r分别是按照记录次数、时间、查询时间、返回的记录数来排序,ac、at、al、ar,表示相应的倒序;
B: -t, 是top n的意思,即为返回前面多少条的数据;
C: -g, 是grep的意思,后边可以写一个正则匹配模式,大小写不敏感的。

找到最慢的一条sql,进行排查,最后定位到就是这条sql导致的问题。因为这条sql算是统计类的sql,要全表扫描,关联的表也比较大,group by字段多, count的字段不是聚集索引,计算量过大cpu一直下不来。

Count: 9  Time=267.50s (2407s)  Lock=0.01s (0s)  Rows=1.0 (9) 

explain

 去掉了大部分无用的字段,count字段改成主键,再看读取成本少了很多

sql优化完了效果其实并不明显,后面又加了redis缓存,使用同步锁

思路:请求接口时,先查缓存,如果没有缓存,先获取锁,获取到了查数据库,查到放入缓存,过期时间配置为1天

加锁其实就是为了解决缓存击穿,高并发访问这个key时,如果缓存失效,大量请求就不会立刻去查数据库。

@Cacheable(value = "xxxx", key = "#root.methodName+'_'+ #a0.pageNo +'_'+ #a0.pageSize", sync = true)
public Data  getList(Page page){
		 //
		return data;			
	}


public class MyCache implements Cache{
    RedisTemplate redisTemplate;

 

    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public String getName() {
        return key;
    }

    public void setName(String key) {
        this.key = key;
    }

    @Override
    public Object getNativeCache() {
        return this.redisTemplate;
    }

    public String getKeyWarp(String key){
        return getName() + key;
    }

    @Override
    public ValueWrapper get(Object key) {
        final String keyf = getKeyWarp(key.toString()) ;
        Object object = redisTemplate.opsForValue().get(keyf);

        return (object != null ? new SimpleValueWrapper(object) : null);
    }

    @Override
    public <T> T get(Object key, Class<T> type) {
        return null;
    }

// 如果sync = true会走这段代码,这里的锁在分布式环境可以改成分布式锁
    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        ValueWrapper storeValue = get(key);
        if (storeValue != null) {
            return (T) storeValue.get();
        } else {
            synchronized(this) {
                storeValue = get(key);
                if (storeValue != null) {
                    return (T) storeValue.get();
                } else {
                    Object value;
                    try {
                        value = valueLoader.call();
                    } catch (Throwable var8) {
                        throw new ValueRetrievalException(key, valueLoader, var8);
                    }
                    put(key, value);
                    return (T) value;
                }
            }
        }
    }

    @Override
    public void put(Object key, final Object value) {
        String strKey = getKeyWarp(key.toString());

        //临时缓存  1天过期
        if(strKey.indexOf("xxxx") > -1   {
            redisTemplate.opsForValue().set(strKey, value);
            redisTemplate.expire(strKey, 1, TimeUnit.DAYS);

        } else {
            redisTemplate.opsForValue().set(strKey, value);
        }
    }

    @Override
    public void evict(Object key) {
        final String keyf = getKeyWarp(key.toString());
        redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                return connection.del(keyf.getBytes());
            }
        });
    }

    @Override
    public void clear() {
    }

 
    @Override
    public ValueWrapper putIfAbsent(Object arg0, Object arg1) {
        return null;
    }
}
@Bean("cacheManager")
    public SimpleCacheManager getSimpleCacheManager(RedisTemplate redisTemplate){
        SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
 
       MyCache myCache= new MyCache();
                mySpringCacheRedisConfig.setName("xxx");
                mySpringCacheRedisConfig.setRedisTemplate(redisTemplate);
                list.add(mySpringCacheRedisConfig); 

        simpleCacheManager.setCaches(list);
        return simpleCacheManager;
    }

参考链接

mysql占用cpu达到100%,解决方案_杨球球0418的博客-CSDN博客_mysql100%

mysqldumpslow 命令以及用法举例_小尖一步的博客-CSDN博客_mysqldumpslow

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值