在線上 有些sql執行的比較慢,但願能夠指定超時時間, 取消這個sql的執行,如下以druid爲例爲實現這個功能java
jdbc 有2個超時時間, 一個是queryTimeout, 一個是socketTimeout, queryTimeout的做用是sql執行超時以後,能夠取消此次的執行,底層原理是發送kill $id通知mysql來中斷這個sql的執行 socketTimeout的做用主要是爲了解決tcp鏈接超時的問題, 超時以後,這個tcp鏈接會斷開 要注意的是,socket超時只是釋放tcp連接, 但sql仍是在mysql裏面執行(能夠經過show processlist來看到) 因此爲了取消sql的執行,socketTimeout的時間必定要大於queryTimeout纔有意義
queryTimeout會拋出異常com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client requestmysql
socketTimeout會拋出異常com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failuresql
The last packet successfully received from the server was 2,020 milliseconds ago. The last packet sent successfully to the server was 2,010 milliseconds ago.socket
能夠看具體示例tcp
public class JdbcTimeout { DruidDataSource dataSource = new DruidDataSource(); @Before public void setUp() { dataSource.setUsername("root"); dataSource.setPassword("123456"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/case?useUnicode=true&characterEncoding=utf-8&socketTimeout=20000000"); dataSource.setQueryTimeout(5); System.out.println("started"); } @Test public void testQuery() throws Exception { try(Connection conn = dataSource.getConnection() ) { try(Statement stmt = conn.createStatement()) { String sql = "SELECT sleep(30*1000), 'name' "; try(ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { String name = rs.getString("name"); System.out.println(name); } } } } } @Test public void testUpdate() throws Exception { String sql = "UPDATE person SET age=3 WHERE id=1 AND SLEEP(30*1000)"; try(Connection conn = dataSource.getConnection() ) { try(Statement stmt = conn.createStatement()) { int updated = stmt.executeUpdate(sql); System.out.println(updated); } } } }