首页 > 解决方案 > 如何在线程中使用超时限制

问题描述

我想在新线程上运行某人的 sql 请求:

#!/usr/bin/env ruby

require 'mysql2'
require 'sequel'

CONF = {
  adapter: 'mysql2',
  encoding: 'utf8',
  username: 'ruby',
  password: 'ruby',
  host: 'localhost',
  port: 3306,
  pool: 4,
  read_timeout:     10,
  write_timeout:    10,
  connect_timeout:  10,
  pool_timeout:     10,
  database: 'demo',
  max_conns: 7
}

conn = Sequel.connect(CONF)

t = Thread.new { conn['select sleep(100)'].all }
sleep 2

t.kill
sleep 15

当我运行此代码时,我预计请求将在 10 秒后停止,但事实并非如此。当查看 mysql 进程列表时:

SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' 

我明白了 - 它仍在处理中(41 秒):

| TIME | QUERY             |  
|------|-------------------|
| 41   | select sleep(100) |

如何更改我的代码以获得预期的结果?

标签: rubythread-safetyconnection-poolingsequel

解决方案


这些_timeout参数是针对客户端使用的 TCPSocket 的,没有设置查询结果的最大等待时间。

您可以使用Timeoutfrom ruby​​ stdlib:

t = Thread.new do
  Timeout.timeout(10) do
    Sequel.connect(CONF)['select sleep(100)'].all
  end
end

注意:Timeout确实存在众所周知的问题,如此处所示

您还可以考虑类似connection_pool gem的东西,它具有超时功能并会为您进行连接池。


推荐阅读