简述
这个工具类主要是为了防止sql卡死或执行时间过长所编写的,这样做可以减少数据库占用资源,是使用定时器进行检测的。下面的案例我就没写定时器了,只是写了检测方法。该方法可以根据需求自己进行修改。
实现
/**测试类 */ 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()); } } }