简体   繁体   English

为什么Timeout.timeout(秒)不能与activerecord一起使用

[英]Why does Timeout.timeout(sec) not work with activerecord

I have the following code running to catch any SQL statements that might get hung. 我运行以下代码来捕获任何可能挂起的SQL语句。 While trying to test this, I wrote a horibly optimized sql statement that takes over a minute to run. 在尝试测试时,我写了一个可怕的优化的sql语句,需要花费一分多钟才能运行。 I put a 20 second timeout wrapper around an activerecord execute sql statement, but it doesn't seem to interrupt the sql call for taking to long. 我在一个activerecord执行sql语句周围放了一个20秒的超时包装器,但它似乎没有中断sql调用for long。 This is running against Oracle databases. 这是针对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

output 产量

  Sql statement took 64 seconds

(Just a guess…) (只是一个猜测......)

Ruby's Timeout.timeout() is probably operating in much the same way as the equivalent function in PHP , which is to say that it counts time executed within Ruby, and stops counting when you're waiting for database queries to run, waiting to finish reading or writing files, waiting to for a network request to complete, etc. — ie waiting for anything IO-related. Ruby的Timeout.timeout()可能与PHP中等效函数运行方式大致相同,也就是说它计算Ruby中执行的时间,并在等待数据库查询运行时停止计数,等待完成读取或写入文件,等待网络请求完成等等 - 即等待与IO相关的任何事情。

Admittedly, I don't have much experience with Rails backed by Oracle, but there's the timeout option in the database config file. 不可否认,我对Oracle支持的Rails没有多少经验,但数据库配置文件中有超时选项。

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

It's in milliseconds. 它以毫秒为单位。

If I can assume you are in the development environment, you might want to explicitly set your explain timeout and review the console log: 如果我可以假设您处于开发环境中,则可能需要显式设置explain超时并查看控制台日志:

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

Remember that ActiveRecord is an ORM , which is to say it's a layer of abstraction that sits on top of your database. 请记住,ActiveRecord是一个ORM ,也就是说它是一个位于数据库顶部的抽象层。

This is important in the context of what happens when Timeout.timeout executes. 这在Timeout.timeout执行时发生的情况很重要。 Database adapters are responsible for taking a command in ruby and converting them into commands that are executed in your database, an entirely different process. 数据库适配器负责在ruby中接受命令并将它们转换为在数据库中执行的命令,这是一个完全不同的过程。

When a timeout happens, the call to @connection.connection.execute , as a ruby command, is interrupted in the adapter but not the sql code itself as you've noted. 发生超时时,作为ruby命令调用@connection.connection.execute会在适配器中被中断,但不会像您所指出的那样在sql代码本身中被中断。

You should be able to make use of the optional Exception Class parameter klass in Timeout.timeout to specify a signal/command to send to your database in order to cancel the query itself. 您应该能够使用Timeout.timeout中的可选Exception Class参数klass来指定要发送到数据库的信号/命令,以便取消查询本身。 However this would depend on your database adapter. 但是,这取决于您的数据库适配器。 Here's the kill query command I would try to execute if I were using mysql. 这是我在尝试使用mysql时尝试执行的kill query命令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM