需求

一个查询耗时过长时,最好能够自动中断,避免阻塞客户端。

功能设计

Kill 查询接口

计划提供两个接口:

  • 查看当前正在执行的查询,参考 Mysql sql 设计为 show query processlist,其结果集如下:

    QueryIdStartTimeSQL
    22020-12-01T14:37:00select * from root.sg.device1;

    对于 SQL 过长(超过64字符)的情况,我们选择展示前面32个字符,以及后面32个字符,例如

    select device1.temperature, device1.speed, device2.status from root.storageGroup1 where time > 2020-12-01T00:00:00 and time < 2020-12-01T23:59:59

    QueryIdStartTimeSQL
    32020-12-01T14:47:00select device1.temperature, devi ... 0 and time < 2020-12-01T23:59:59;
  • 根据 queryId 取消对应查询,sql 设计为 kill query N,其中 N 为 queryId

查询取消的实现逻辑如下:

记录每个查询的执行线程,如果查询被取消,则将线程中断状态设为 true。同时在 SeriesReader 中设置检查点,如果检测到当前线程中断状态为 true,则抛出一个运行时错误,在 TSServiceImpl 中捕获这个错误,并向客户端返回查询取消的错误信息(可能是手动取消或查询超时)。

对于多线程异步执行的原始数据查询,在消费者线程,即主线程每次从阻塞队列中取数据前检查主线程是否被中断,如果被中断则抛出运行时错误,并在 TSServiceImpl 中捕获。消费者线程如果通过了取数据前的检查,而查询刚好在取数据过程中被中断,则此时消费者线程无法被成功中断。因此,在每个查询子线程执行查询前检测主线程的状态,如果主线程的中断状态为 true,则直接返回一个 ExceptionBatchdata,不再进行查询。在消费者主线程从阻塞队列中取数据时,检测到该错误数据,即可将 Exception 向上抛出,从而在 TSServiceImpl 中捕获。

超时参数

首先提供一个全局变量,作为默认的超时时间,如果用户没有未当前查询设定超时时间,则以全局时间为准。

在 JDBC 和 Session 支持在参数中为当前查询设定 timeout 参数,有手动设定超时时间的查询则以该私有时间为主。

监控线程

为了判断查询是否超时,在每个查询开始时,为该查询注册一个 timeout 时间后的定时任务。如果 timeout 时间后,queryId 仍然存在,则调用取消查询接口将查询 kill。

讨论

  1. 查询多长时间默认设为超时合适?(用户可调)

  • No labels

6 Comments

  1. 1.查询多长时间默认设为超时合适(用户可调)?

    默认不设置超时时间,如果没有设置超时时间,IoTDB启动时,则无需启动监控线程。

    2.监控线程多长时间检查一次查询状态合适?

    我觉得启动一个监控线程去轮询有些耗时耗力,并且对于超时时间不同的查询,这个轮询间隔不好控制,所以我觉得在TSServiceImpl里创建一个新的

    ScheduledExecutorService,对于设置了超时时间的查询,向其中submit一个定时任务即可,这样,内存中也无需存储每个查询的超时时间了。
      1. -1... 查询超时应该是默认存在的,不应该用户不设就不做超时处理。。这样不合理。
      2. Big +1.
        1. 设置个默认超时时间吧,比如1分钟。再增加一个动态加载的功能,用户如果发现默认的不合适,可以在线调整默认值
  2. Yuan Tian's comments on Default time is reasonable. Imagine, if there is a system wide default timeout, it means all the queries will be subject for this timeout control and all the queries need to be registered into Monitor Thread to become a timed task, doesn't it? There might be a new service pool of threads needed to be waiting for events, which will wake up one thread in the pool to check if the timed query has finished or not. If does finish, remove from the registration; if not, do 'kill' on the query task.

  3. Besides, there are quite some privilege setup needs to be implemented, connection-level, user-level, query-level, system-level, and user privilege to set timeout through command. The complication is on how the multiple levels of timeout setting will interact with each other (need a component to resolve before a query starts executing).

  4. 补充说明Query timeout、Kill Query、 ResultSet.close、EndQuery的关系。


    查询结束的方式有多少种?每种对后台的资源处理逻辑是什么?