SQL检测超时工具类

1.简述

  这个工具类主要是为了防止sql卡死或执行时间过长所编写的,这样做可以减少数据库占用资源,是使用定时器进行检测的。下面的案例我就没写定时器了,只是写了检测方法。该方法可以根据需求自己进行修改。

2.实现

/**测试类
 */
public class Test{
    public static void main(String[] args) {
        SqlCheckUtils.checkSqlQueryTime();
    }
}
/**SQL检查工具类
 */
class SqlCheckUtils {
    private static Log log = LogFactory.getLog(SqlCheckUtils.class);
    private static int recodeTime = 3;//超过该时间,则记录日志(单位:秒 )
    private static int killTime = 3;//超过该时间,则杀死语句(单位:秒 )
    private static String sql = "show full processlist";//查询哪些线程正在运行,注:Mysql是使用这条语句,其他数据库可更换
    
    public static void checkSqlQueryTime(){
        Connection con = getConnection();//获取数据库连接,这里是随便写的,可以换成自身项目使用的
        Statement st = null;
        ResultSet set = null;
        try {
            st = con.createStatement();
            set = st.executeQuery(sql);
            boolean isHave = false;
            while(set.next()){
                int time = set.getString("time") != null ? Integer.parseInt(set.getString("time")) : 0;//持续的时间,单位是秒
                String state = set.getString("state");//当前连接的sql语句的状态
                if("Copying to tmp table".equalsIgnoreCase(state) //复制临时表
                        || "Writing to net".equalsIgnoreCase(state) //正在将数据包写入网络
                        || "Sending data".equalsIgnoreCase(state) //SQL正在处理 SELECT 查询
                        || "Sorting for group".equalsIgnoreCase(state) //SQL正在 GROUP BY 做排序
                        || "Sorting for order".equalsIgnoreCase(state)//SQL正在 ORDER BY 做排序
                        || "Sorting index".equalsIgnoreCase(state) //根据索引排序
                        || "Sorting result".equalsIgnoreCase(state) //创建索引
                        || "statistics".equalsIgnoreCase(state) //统计数据
                        || "Waiting for tables".equalsIgnoreCase(state)//数据表结构被修改了,需要重新打开数据表以取得新的结构。为了能的重新打开数据表,必须等到所有其他线程关闭这个表
                        || "Copying to tmp table on disk".equalsIgnoreCase(state)){//复制临时表,临时结果集大于tmp_table_size
                    
                    String id = set.getString("id");//标识,用于kill一个语句
                    if(time > killTime){//当前持续时间是否大于指定时间,是的话添加kill语句当前命令列表中
                        isHave = true;
                        st.addBatch("kill "+id);
                    }
                    if(time > recodeTime){//当前持续时间是否大于指定时间,是的话记录日志
                        String user = set.getString("user");//单前用户
                        String host = set.getString("host");//端口,可以知道是由哪个ip的哪个端口上发出的
                        String db = set.getString("db");//当前连接的是哪个数据库
                        String command = set.getString("command");//前连接的执行的命令,休眠(sleep)、查询(query)、连接 (connect)
                        String info = set.getString("info");//sql语句,因为长度有限,所以长的sql语句就显示不全
                        StringBuffer sb = new StringBuffer();
                        sb.append("database lock(>"+recodeTime+"): id(").append(id).append("), user(").append(user).append("), host(")
                            .append(host).append("), db(").append(db).append("), command(").append(command).append("), time(")
                            .append(time).append("), state(").append(state).append("), info(").append(info).append(")   ");
                        log.error(sb.toString());
                    }
                }
            }
            set.close();
            if(isHave){//批量执行此列表中的命令
                st.executeBatch();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            close(set , st , con);//释放资源
        }
    }
    /**获取数据库连接
     */
    private static Connection getConnection(){
        Connection connection = null ;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mybatis?"+
            "zeroDateTimeBehavior=convertToNull&useSSL=false&useUnicode=true&characterEncoding=UTF-8";
            String user = "root" ;
            String pass = "123456" ;
            connection = DriverManager.getConnection(url, user, pass);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null ;
        }
        return connection ;
    }

    /**释放资源
     */
    private static void close(ResultSet rs ,Statement st ,Connection ct){
        try {
            if(null != rs && !rs.isClosed()){
                rs.close();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        try {
            if(null != st && !st.isClosed()){
                st.close();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        try {
            if(null != ct && !ct.isClosed()){
                ct.close();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/bl123/p/13752932.html