定時查詢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;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章