昨天在碰到一个dremio jdbc 比较奇怪的问题,按照了标准的jdbc 操作(建立链接,创建Statement,处理数据,关闭Statement,关闭连接)
当进行多次执行(多次建立连接操作)发现dremio 有一个操作异常,造成数据表创建有问题(事务不完整)
参考代码
private static void v3() {
try {
String sql = " select * from pg.public.sensor";
String url = "jdbc:dremio:direct=localhost:31011;schema=sys";
Connection conn1 = DriverManager.getConnection(url, "xxxx", "xxxxx");
//3.获取Statement对象
Statement statement1 = conn1.createStatement();
statement1.executeQuery(sql);
statement1.close();
conn1.close();
String sql2 = " select * from pg.public.sensor";
Connection conn2 = DriverManager.getConnection(url, "dalong", "dalong123");
Statement statement2 = conn2.createStatement();
statement2.executeQuery(sql2);
statement2.close();
conn2.close();
String sql3 = " select * from pg.public.sensor";
Connection conn3 = DriverManager.getConnection(url, "dalong", "dalong123");
Statement statement3 = conn3.createStatement();
statement3.executeQuery(sql3);
statement3.close();
conn3.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
注意上边我们没有执行进行数据的处理statement.executeQuery 部分
错误信息
Query cancelled by user 'xxxxx'
解决方法
通过简单跟进代码发现,提示信息是争取的,因为我们进行了 statement 的close 内部使用了游标,dremio 发现如果内部执行还没完成的时候执行
进行close 会通过dremio client 发送一个cancel query 的rpc 请求(dremio 内部是基于job 调度的,具体任务什么时是否完成不太确定),如果进行了
数据查询获取,这样dremio jdbc 就可以知道啥时数据是完成的(内部通过游标遍历),然后close 肯定也没有问题,最好的实践方法我们是通过连接池
工具,这样可以进行连接的服用,确保连接不会出现问题,同时也有利于资源的管理
连接池使用
可以通过hikari 包, 当然实际使用中我们一般都是集成服务集成的(比如spring boot) 基于datasource 是更好的选择
参考资料
https://github.com/brettwooldridge/HikariCP
https://github.com/dremio/dremio-oss/blob/master/client/jdbc/src/main/java/com/dremio/jdbc/impl/DremioCursor.java#L427
https://github.com/dremio/dremio-oss/blob/master/client/jdbc/src/main/java/com/dremio/jdbc/impl/DremioResultSetImpl.java