定时查询DB记录返回条数和耗时

我接到一个需求,要用脚本来查询DB并记录返回条数和耗时。脚本要能做到一次查询,和定时查询。工具配置文件里定义好query和执行次数,每个query执行这么多次后,计算出一个平均耗时。

  • 一次查询的话结果写入csv文件,结束。
  • 定时查询的话,用户定义好时间点,每天的这个时候开始查询,每次结果append到csv文件里
  • 另外给用户一个timeout setting,有时候某个表正在刷新,或者有问题,那么query的时候就需要很久很久都不会返回结果,整个工具就会卡住。所以根据用户的timeout setting,如果一个query超过10分钟还没有返回,结果里记录timeout然后接着跑下一个query

一次查询的话,非常简单。

定时查询的话,用到了org.quartz-scheduler。

第一步,定义一个自己的job类来实现Job接口的execute()方法,这个方法定义了每次执行job的具体步骤。参数JobExecutionContext context非常有用,通过它可以拿到job details还有要传递给job的参数(JobDataMap)。

 public class MyOwnJob implements Job 
{
    public void execute(JobExecutionContext context) throws JobExecutionException 
    {
    	...
    }
}
JobDataMap datamap = paramJobExecutionContext.getJobDetail().getJobDataMap();

第二步,实现Schedule:使用JobBuilder新建MyOwnJob的实例 >> 将想要传递给MyOwnJob的参数放入JobDataMap >> 用CronExpression建立trigger >> 将JobDetail 实例和trigger加入到scheduler里去

public void ceateJobSchedule(...){
	JobDetail jobD = JobBuilder.newJob(MyOwnJob.class).withIdentity(jobName, groupName).build();
	jobD.getJobDataMap.put(parameter,value);
	Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName).withSchedule(CronScheduleBuilder.cronSchedule(cronExp)).build();
	scheduler.scheduleJob(jobD, trigger);
	scheduler.start()

需要注意的是,到了时间点,Quartz就会起一个线程,新建一个MyOwnJob的实例来执行MyOwnJob.execute()方法。MyOwnJob类里面存结果的属性或者结构不要定义成static的,否则不同线程之间会互相干扰,结果会混在一起…

至于DB query的timeout,一般的DB driver都有timeout设置,偏巧我们用到的这个数据中心自己的build的DB driver没有实现timeout。那好吧,自己动手.

打个比方,DAO里面有一个query(String query)方法,想要给这个方法设置一个timeout,那么,新建一个queryWithTimeoutSetting()方法,在新方法里,创建FutureTask实例,把之前的query()方法包进去,FutureTask.get()执行并捕捉time out exception.

public Integer queryWithTimeoutSetting(int timeOut, String query){
	FutureTask<Integer> fTask = new FutureTask<Integer>(
		new Callable<Integer>(){
			public Integer call() throws SQLException{
					return query(String query);
			} 
		}
	);
	ExecutorService executor = Executors.newSingleThreadExecutor();
	executor.execute(fTask);
	try{
		int result = fTask.get(timeOut, TimeUnit.MINUTES);
	} catch (ExecutionException e){
		fTask.cancel(true);
	} catch (TimeoutException e){
		//deal with time out....
		fTask.cancel(true);
	} finally {
		fTask.cancel(true);
		executor.shutdown();
		return result;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章