首页 > 数据库 >mysql慢sql监控

mysql慢sql监控

时间:2023-02-14 14:35:46浏览次数:50  
标签:log sql params 监控 mysql import append

1、思路

之前用 mysql 一直没有考虑到这点,mysql 慢 sql 监控是很重要的,它能帮我们梳理我们的业务 sql 到底是哪里处了问题,那么慢 sql 监控怎么做呢?

有两种思路来实现

在应用层做

比如我们的系统使用 mybatis,则可以使用 mybatis 的拦截器,在想要监控的 sql 前后进行即时,超时后打 error 日志。如果日志接入日志平台,那么日志平台可以配置报警邮件,直接发邮件提醒开发。

在 mysql 层做

mysql 开启慢日志,记录慢查询 sql。可以读取慢查询日志,分析哪些 sql 属于慢查询,然后发邮件提醒等。这等于做了一个慢 sql 预警系统,一般大公司都会有这样的一套系统(https://github.com/wxisme/slowsql-monitor 类似于这种)。
开启 mysql 慢查询日志的方法如下(https://github.com/wxisme/slowsql-monitor 可以参照这个工程):

--1.First configure the MySQL slow query log,you need to log in to the mysql client. Turn on MySQL slow query log switch:
show variables like 'slow_query_log';
set global slow_query_log='ON';

--2.Set the long query time in seconds:
show variables like 'long_query_time';
set global long_query_time=1;

--3.Set the log queries not using indexes:
show variables like 'log_queries_not_using_indexes';
set global log_queries_not_using_indexes='ON';

--4.show slow log location:
show variables like 'slow_query_log_file';

mysql 的 slowlog 的内容如下:

/usr/local/mysql/bin/mysqld, Version: 5.7.28-log (MySQL Community Server (GPL)). started with:
Tcp port: 3306  Unix socket: /tmp/mysql.sock
Time                 Id Command    Argument
# Time: 2021-04-10T07:22:09.260226Z
# User@Host: root[root] @ localhost [127.0.0.1]  Id:  7405
# Query_time: 0.247682  Lock_time: 0.025775 Rows_sent: 103  Rows_examined: 103
use deepwise;
SET timestamp=1618039329;
/* ApplicationName=DataGrip 2018.3.1 */ SELECT t.* FROM deepwise.DW_AI_RESULT t
LIMIT 501;
# Time: 2021-04-10T07:22:37.999494Z
# User@Host: root[root] @ localhost [127.0.0.1]  Id:  7406
# Query_time: 0.018695  Lock_time: 0.017633 Rows_sent: 0  Rows_examined: 0
SET timestamp=1618039357;
/* ApplicationName=DataGrip 2018.3.1 */ SELECT t.* FROM deepwise.dw_ai_result_process t
LIMIT 501;
# Time: 2021-04-10T07:23:04.504722Z
# User@Host: root[root] @ localhost [127.0.0.1]  Id:  7404
# Query_time: 0.008424  Lock_time: 0.002104 Rows_sent: 0  Rows_examined: 103
SET timestamp=1618039384;
/* ApplicationName=DataGrip 2018.3.1 */ select * from DW_AI_RESULT where PATIENT_ID like '%4468%';

剩下的就是解析这个 log 日志,然后把数据给前端进行页面渲染什么的。

其他用法:

https://zhuanlan.zhihu.com/p/565812229

mybatis 拦截器方案

package com.best.ecboss.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;

import java.beans.PropertyDescriptor;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

@Intercepts(
        @Signature(type = Executor.class, method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
)
public class QueryDaoMybatisInterceptor implements Interceptor {

    private final Log logger = LogFactory.getLog(QueryDaoMybatisInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs(); //方法参数
        Date begin = new Date();
        Object ret = invocation.proceed();
        Date end = new Date();
        try {
            MappedStatement mappedStatement = (MappedStatement) args[0];
            // 方法参数
            Object params = args[1];
            // mapper 中的方法名称,如 “com.xushu.mysql.slowsql.dao.AccountMapper.selectList”
            String mapperId = mappedStatement.getId();
            // 获取 sql 语句,并格式化 sql,将很多空格替换成一个空格
            String sql = formatSql(mappedStatement.getBoundSql(params).getSql());

            log(mapperId, sql, params, begin, end);
        } catch (Exception e) {
        }
        return ret;
    }

    private String formatSql(String sql) {
        return sql.replaceAll("\\s+", " ");
    }

    private void log(String statementId, String sql, Object params, Date begin, Date end) {
        // 这边可以记录自己想要的查询方法,比如 “selectList”
        if (statementId == null || !statementId.contains(".selectList")) {
            return;
        }
        long ms = end.getTime() - begin.getTime();
        String paramStr = parseParams(params);
        if (ms > 10000) {
            logger.error("ms:[" + ms + "],sql:" + sql + ",param:[" + paramStr + "]");
        } else if (ms > 1000) {
            logger.warn("ms:[" + ms + "],sql:" + sql + ",param:[" + paramStr + "]");
        } else {
            logger.info("ms:[" + ms + "],sql:" + sql + ",param:[" + paramStr + "]");
        }
    }

    // 格式化传参
    private String parseParams(Object params) {
        StringBuilder sb = new StringBuilder();
        try {
            if (params instanceof Map) {
                Map map = (Map) params;
                map.forEach((k, v) -> {
                    sb.append(",").append(k).append(":").append(v);
                });
            } else if (BeanUtils.isSimpleProperty(params.getClass())) {
                sb.append(",").append(params.getClass().getSimpleName()).append(":").append(params).append(",");
            } else {
                // 反射getter属性
                PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(params.getClass());
                for (PropertyDescriptor pd : pds) {
                    if (pd.getReadMethod() != null && !"class".equals(pd.getName())) {
                        String name = pd.getName();
                        Object value = null;
                        value = pd.getReadMethod().invoke(params);
                        sb.append(",").append(name).append(":").append(value);
                    }
                }
            }
        } catch (Exception e) {
        }
        if (sb.length() > 0) {
            return sb.toString().substring(1);
        }
        return "";
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

作者:放开那个BUG
链接:https://www.jianshu.com/p/24a42bcd6ef8
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:log,sql,params,监控,mysql,import,append
From: https://www.cnblogs.com/qds1401744017/p/17119475.html

相关文章

  • myisql索引调优
    Mysql索引为什么选择B+树这种数据结构1、二叉树无法解决单边增长的问题。2、红黑树虽然可以通过节点旋转来达到节点自动平衡的问题、但无法有效控制树的高度。3、B树、B......
  • Java中通过jdbc连接MySQL数据库的代码封装-简历版本【杭州多测师_王sir】【杭州多测师
    本次封装类分为两大块:db.properties(配置文件),JDBCUtil类(初始化,连接,关闭)。 db.properties配置文件driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:33......
  • SQL SERVER备份数据库到共享目录
    --如果xp_cmdshell没有启用,请先启用sp_configure'showadvancedoptions',1RECONFIGUREGOsp_configure'xp_cmdshell',1RECONFIGURE--目标共享目录:\\172.16.1.63......
  • Mysql查询所有表+字段
    先上代码SELECTt1.TABLE_SCHEMA,t1.TABLE_NAME,t2.TABLE_COMMENT,t1.COLUMN_NAME,t1.COLUMN_COMMENT,t1.COLUMN_TYPEFROMinformation_schema.COLUMNSt1innerj......
  • mysql报错:MySQL server has gone away
    一、报错提示:   二、报错原因:原因一:一种可能是发送的SQL语句太长,以致超过了max_allowed_packet的大小,如果是这种原因,你只要修改my.cnf,加大max_allowed_pac......
  • MySQL-比较两个表不同的数据
    原文链接:https://blog.csdn.net/JustDI0209/article/details/1224922931.需求:一份数据有新旧两个版本,想比较一下有哪些地方不同。2.方法:创建一个复制表,并将新数据导入,执......
  • 基于多云构建监控告警系统
    之前有一个系列的文章来讲我们多云系统的设计与落地,多云系统实现了云上资源的统一管理,同时基于关联关系构建了清晰的资源拓扑,其中基于业务的资源拓扑应用最为广泛,也就是我......
  • Win部署MySQL5.7
    Win部署MySQL5.7压缩包安装参考引用连接即可如果机器中部署多个MySQL,则应当合理配置系统服务和my.ini服务环境变量MYSQL57_HOMED:\ProgramFiles\mysql-5.7.39-......
  • SQL Server 只有数据库文件,没有日志文件,恢复数据时报1813错误的解决方案
    无法打开新数据库'ASR'。CREATEDATABASE中止。文件激活失败。物理文件名称'E:\SqlServer\MSSQL\Data\ASR_log.LDF'可能不正确。无法重新生成日志,原因是数据库关闭时存......
  • 为SQL Server配置连接加密
    前言很多客户在对数据库做安全审计时要求配置连接加密,本文就如何配置加密以及使用证书做一个系统的整理。1连接加密首先,连接加密不是透明数据加密,很多人经常把两个概念混淆......