【问题标题】:Why does Timeout.timeout(sec) not work with activerecord为什么 Timeout.timeout(sec) 不适用于 activerecord
【发布时间】:2014-04-29 05:27:08
【问题描述】:

我运行以下代码来捕获任何可能挂起的 SQL 语句。在尝试对此进行测试时,我编写了一个经过优化的 sql 语句,运行时间超过一分钟。我在 activerecord 执行 sql 语句周围放置了一个 20 秒的超时包装器,但它似乎并没有因为需要很长时间而中断 sql 调用。这是针对 Oracle 数据库运行的。

  start_time = Time.now
  Timeout.timeout(20) do #20 timeout for long running sql
    @connection.connection.execute(sql_string)
  end
  total_sql_time = Time.now - start_time
  puts "Sql statement took #{total_sql_time} seconds

输出

  Sql statement took 64 seconds

【问题讨论】:

  • postgresql 不是这种情况。这样做Timeout.timeout(2) { Product.connection.execute('select pg_sleep(10) ') } 将调用异常。
  • @ParitoshPiplewar Mine 调用异常但是在抛出异常之前它仍会等待获取响应
  • 问这个问题的最佳地点是 oracle-enhanced_adapter 的邮件列表。当我使用 Oracle 时,它​​回答了各种类似的问题。

标签: sql ruby-on-rails ruby activerecord timeout


【解决方案1】:

(只是猜测……)

Ruby 的Timeout.timeout() 的运行方式可能与equivalent function in PHP 大致相同,也就是说,它计算在 Ruby 中执行的时间,并在您等待数据库查询运行时停止计算,等待完成读取或写入文件,等待网络请求完成等——即等待任何与 IO 相关的内容。

【讨论】:

    【解决方案2】:

    请记住,ActiveRecord 是一个ORM,也就是说它是位于数据库之上的抽象层。

    这对于Timeout.timeout 执行时发生的情况很重要。数据库适配器负责在 ruby​​ 中获取命令并将它们转换为在数据库中执行的命令,这是一个完全不同的过程。

    当发生超时时,对 @connection.connection.execute 的调用(作为 ruby​​ 命令)会在适配器中中断,但不会像您所指出的那样中断 sql 代码本身。

    您应该能够使用Timeout.timeout 中的可选异常类参数klass 来指定要发送到数据库的信号/命令,以取消查询本身。但是,这取决于您的数据库适配器。 Here's kill query 命令如果我使用mysql,我会尝试执行。

    【讨论】:

    • 实际上,ruby 命令似乎并没有在适配器中被中断,因为即使我达到了超时,程序也会等待,直到它从查询中得到响应。
    • 查看更新的问题...这将更清楚地说明我的意思是它不会杀死线程
    • 我猜 Oracle 适配器以某种方式导致全局解释器锁没有被释放 - 这是唯一可以打破 Timeout.timeout 的事情,因为解释器(或虚拟机)直到重新获得控制权SQL 数据到达。你能用 JRuby 和 Oracle JDBC 驱动试试这些东西吗?
    • @GaborGarami 我实际上是在使用 JRuby 和 Oracle JDBC 驱动程序 (OJDBC6.jar) 以下是我的 Gemfile 中的记录。 gem 'activerecord', '4.0.4' gem 'ActiveRecord-JDBC', '0.5' gem 'activerecord-jdbc-adapter', '1.3.6'
    【解决方案3】:

    诚然,我对 Oracle 支持的 Rails 没有太多经验,但数据库配置文件中有超时选项。

    # config/database.yml
    production:
      ...
      timeout: 20000
    

    以毫秒为单位。

    如果我可以假设您在开发环境中,您可能需要明确设置您的 explain 超时并查看控制台日志:

    # config/environments/development.rb
    config.active_record.auto_explain_threshold_in_seconds 20
    

    【讨论】:

    • 你有链接让我可以多读一点超时吗?我读到的所有内容都是关于连接超时而不是运行 sql timeout
    猜你喜欢
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    相关资源
    最近更新 更多