查询结束的方式

查询结束一共有四种方式

客户端获得结果集后,连接异常断开

thrift检测到连接断开后,会调用handleClientExit()方法,里面会调用closeSession()方法以及releaseQueryResource方法释放查询资源,但是如果是不带值过滤的原始数据查询,主线程虽然随着连接断开,完成资源释放后而停止工作,但是由于这种查询是多线程并行的,会有多个异步的并行线程去读取数据,这些线程没有退出,依旧在后台运行。

客户端获得结果集后,主动调用close方法

  1. 客户端遍历完结果集后,调用close方法,server调用releaseQueryResource释放查询资源,即使是不带值过滤的原始数据查询,由于数据已经读取完成,多个异步的并行线程已经读取完数据而自动退出,主线程完成资源释放后也会退出
  2. 客户端未遍历完结果集,中途调用close方法,releaseQueryResource虽然查询资源会正常释放,但是如果是不带值过滤的原始数据查询,主线程虽然随着连接断开,完成资源释放后而停止工作,但是由于这种查询是多线程并行的,会有多个异步的并行线程去读取数据,这些线程没有退出,依旧在后台运行。

执行kill query命令

server端会调用QueryTimeManager.killQuery()方法,设置查询的中断标记位为true,之后查询线程运行到设置的检查点时,会判断查询有没有被中断,如果被中断,则抛出QueryTimeoutRuntimeException异常,server捕获此异常后,调用releaseQueryResource释放查询资源,但是如果是不带值过滤的原始数据查询,主线程虽然随着连接断开,完成资源释放后而停止工作,但是由于这种查询是多线程并行的,会有多个异步的并行线程去读取数据,这些线程没有退出,依旧在后台运行。

这里也存在一个问题,若客户端连接此时没有断开,并且客户端也没有继续调用next(),则执行kill query命令,也没有办法清理查询资源,因为此时server端并没有活跃的线程与客户端对应,也就没有机会断查询有没有被中断。

查询超时,自动退出

若开启了查询超时功能,每个查询会有一个后台的定时线程,等待设定的查询超时的时长后,若此次查询还未结束,则将此次查询的中断标记位为true,之后查询线程运行到设置的检查点时,会判断查询有没有被中断,如果被中断,抛出QueryTimeoutRuntimeException异常,server捕获此异常后,调用releaseQueryResource释放查询资源,但是如果是不带值过滤的原始数据查询,主线程虽然随着连接断开,完成资源释放后而停止工作,但是由于这种查询是多线程并行的,会有多个异步的并行线程去读取数据,这些线程没有退出,依旧在后台运行。


存在的问题

对于不带值过滤的原始数据查询而言

  1. 如果客户端未遍历完结果集就调用close方法,或异步读取数据的线程未结束前,客户端连接异常断开,则异步的读取线程无法退出,会一直占着资源。
  2. 如果用户执行kill query命令或查询超时,若中断标记位首先被主线程捕获,主线程抛出异常后,就会清除中断标记,导致异步读取数据的线程依旧无法退出;即使中断标记位首先被某一异步读取数据线程捕获,当前异步读取线程和主线程能够正常退出,但是该查询的其他异步读取线程也无法正常退出。
  3. 如果用户执行kill query命令,客户端连接此时没有断开,并且客户端也没有继续调用next(),则执行kill query命令,也没有办法清理查询资源,因为此时server端并没有活跃的线程与客户端对应,也就没有机会断查询有没有被中断。




  • No labels

2 Comments

  1. 多年C++编程带来的习惯是资源使用的管理,这里也适用:任何时候适用/分配/启动资源(memory,lock,file handler, socket, thread, share memory, etc.),我们都要想着这个资源怎样被回收(包括在哪里被回收),出现异常时怎样被回收或释放,特别是在跨线程甚至跨进程的系统里。可以在设计时考虑到,或直接在相关代码处先加注释,这对7x24的系统软件的稳定性是个必要条件。

  2. 问题3里,查询执行完成返回结果集后,server 端没有活跃的查询线程,即使用户尝试 show query processlist 查看当前查询列表也是检查不到查询的,这时资源主要由 resultSet 占用,执行 kill query 要释放什么资源?