시간 초과된 DB 조회를 중지하는 방법

6028 단어 timer
자세히 보기
하나.문제: 때때로 우리가 실행하는 DB 조회(예를 들어 일부 조회의 저장 프로세스)는 시간이 너무 길다. 우리의 코드가 논리적으로 이렇게 오래 기다리고 싶지 않을 때 어떻게 삭제합니까?
 
둘.생각: 먼저 "select connection Id ()"를 사용한 다음 "kill query id"문구를 통해 대응하는 DB 프로세스를 삭제합니다.나중에 JdbcTemplate에서CallableStatement의cancel()이 저장 프로세스의 호출을 끄는 것을 발견했다.그러면 우리는 Timer와 결합하여 시간을 계산할 수 있으며, N분이 넘으면 cancel () 을 실행하면 된다.
 
셋.코드:
1.task 정의: (connection Id에 맞추어 추적할 수 있습니다. 논리적으로는 사용되지 않았지만)
public class CustomTimeTask extends TimerTask {
	private static final Logger logger = LoggerFactory.getLogger(CustomTimeTask.class);
	
	CallableStatement cs ;
	int id;
	
	public CustomTimeTask(CallableStatement cs, int id) {
		super();
		this.cs = cs;
		this.id = id;
	}

	@Override
	public void run() {
		try {
			logger.info("[Timeout]TimeTask try to cancel the long time procedure query. Connection ID is [{}]", id);
			cs.cancel();
		} catch (Exception e) {
			logger.error("[Timeout]TimeTask fail to cancel the long time procedure query. Please check the if the query has been stopped in database. "
					+ "The connection ID is [{}]", id);
		}
	}

}

 
2. 실행:
logger.debug("-----------Start to call CSV store procedure------------");
		Connection conn = null;
		CallableStatement cs = null;
		ResultSet rs = null;
		
		Timer timer = null;
		boolean isQuery = false;
		
	......
		try{
			conn = jdbcTemplate.getDataSource().getConnection();
			cs = conn.prepareCall(foo);
			....
			
			isQuery = true;
			int queryTimeoutMins = SystemConfig.getQueryTimeout();
			if(queryTimeoutMins>0) {
				logger.debug("Execute the statemnet to call procedure  to connection ID [{}]. "
					+ "And start the timer to cancel the timeout query. Timeout setting [{} minutes]"
						,conID,queryTimeoutMins);
				CustomTimeTask customTimeTask = new CustomTimeTask(cs, conID);
				timer = new Timer();
				timer.schedule(customTimeTask, queryTimeoutMins * 60 * 1000);
			}else {
				logger.debug("Execute the statemnet to call procedure to gen CSV record to connection ID [{}]. "
						+ "But not start the timer to cancel the timeout query because timeout setting is [{} minutes]"
						,conID,queryTimeoutMins);
			}
			
			cs.execute();
			if(timer != null) {
				logger.debug("The query for connection ID [{}] is completed. "
					+ "Cancel the timer and begin to get the resultSet. ",conID);
				timer.cancel();
				timer.purge();
			}else {
				logger.debug("The query for connection ID [{}] is completed. Begin to get the resultSet.",conID);
			}
			isQuery = false;
			
			rs = cs.getResultSet();
			
			.........
			
			...........
			
			rs.close();
		}catch (DataAccessException e) {
			dbLogger.error("DB is down. Exception is [{}]", e.getMessage());
			try {
				if(isQuery && cs!=null && !cs.isClosed()) {
					logger.info("Program has begun the query. Try to cancel the procedure query for connection ID [{}]"
							, conID);
					cs.cancel();
				}
				
			} catch (MySQLStatementCancelledException e1) {
				logger.info("Successfully cancel the procedure query for connection ID [{}]"
						, conID);
				if(timer != null) {
					timer.cancel();
					timer.purge();
				}
				isQuery = false;
			} catch (Exception e1) {
				logger.error("-- Error occur when try to cancel the query for connection ID[{}]. "
						+ "Exception is [{}].",conID, e.getMessage());
			}
			throw e;
			
		} catch (MySQLStatementCancelledException e) {
			logger.info("Successfully cancel the procedure query for connection ID [{}]"
					, conID);
			if(timer != null) {
				timer.cancel();
				timer.purge();
			}
			isQuery = false;
			return null;
		}catch (Exception e) {
			logger.error("-- Error occur, exception is [{}]", e.getMessage());
			logger.error("DB: error:", e);
			try {
				if(isQuery && cs!=null && !cs.isClosed()) {
					logger.info("Program has begun the query. Try to cancel the procedure query for connection ID [{}]"
							, conID);
					cs.cancel();
				}
				
			} catch (MySQLStatementCancelledException e1) {
				logger.info("Successfully cancel the procedure query for connection ID [{}]"
						, conID);
				if(timer != null) {
					timer.cancel();
					timer.purge();
				}
				isQuery = false;
			} catch (Exception e1) {
				logger.error("-- Error occur when try to cancel the query for connection ID[{}]. "
						+ "Exception is [{}].",conID, e.getMessage());
			}
			
			return null;
		}finally {
			try {
				if (rs != null)
					rs.close();
				if (cs != null)
					cs.close();
				if (conn != null) {
					conn.close();
				}
			} catch (Exception e) {
				logger.error("Error occurs when close the connection to database. Error:", e);
				return null;
			}
			
		}
		logger.debug("-----------End to call store procedure------------");
		return resultMap;
	}

 
몇 가지 주의할 점이 있습니다. 생략된 부분은 정상적인 cs 실행 저장 프로세스의 처리입니다.그러나 timer에 대해 판단해야 한다.
1.조회가 끝났으면 schedule을 기다릴 필요가 없습니다.timer를 취소해야 합니다
2. DB가 잘못되면 조회 여부를 판단하고 cs가close인지 확인하십시오. 그렇지 않으면 cs를 호출해야 합니다.cancel () 로 끝내기
3. 동시에 cs를 주의한다.cancel () 후 timer가 끝났는지 여부

좋은 웹페이지 즐겨찾기