4

感谢您的关注。经过一段时间的空闲期后,我们有点卡住了连接,如果有任何帮助或尝试的事情,我们将不胜感激。

我们在 jruby 1.7.2 上的 Sinatra 应用程序中使用 v1.4.1 的 activerecord-oracle_enhanced-adapter 和 ojdbc6.jar。我的控制器调用一个辅助类方法并返回一个 json 字符串。帮助类方法只是查询 Oracle 数据库中的数据。代码如下所示:

class App < Sinatra::Base
  get '/customer/:id_number' do |id_number|
    MyHelper.customer(id_number).to_json
  end
end

class MyHelper
  @dbconfig = YAML.load_file("../config/database.yml")
  @dbenv = @dbconfig["#{settings.environment}"]

  puts "establish_connection"
  ActiveRecord::Base.establish_connection(@dbenv)

  def self.customer(id_number)
    begin
      query = <<-SQL
        SELECT * FROM customer WHERE cust_id = '#{id_number}'
      SQL
      puts 1
      ActiveRecord::Base.connection.exec_query(query)
      puts 2
    rescue => e
      puts 3
      puts e.message
    ensure
      puts 4
      ActiveRecord::Base.clear_active_connections!
      puts 5
    end
   end
end

我们有一个 shell 脚本,它点击控制器 50 次,休眠 2 小时并重复。我们可以在开始时看到一个对建立连接的调用(预期)。我们没想到的是,在睡眠之后,第一次连接到数据库总是卡住。我们在日志中看到的只是“1”。15 分钟后,客户端超时并再次调用控制器。第二个调用似乎具有“唤醒”连接池的效果,因为它总是恢复线程 1,因此我们会看到“2”、“4”和“5”。同时,我们还会看到线程 2 的日志消息:“1”、“2”、“4”和“5”。我们知道是因为实际代码将 Thread.current.object_id 作为消息的一部分打印。

我们尝试添加 ActiveRecord::Base.connection.verify!就在 exec_query 之前,但这只会将卡住的调用转移到验证行。

我们是否正确使用了适配器?还有什么我们可以尝试的吗?

4

1 回答 1

0

我已经使用事件机和 oracle 适配器实现了一个解决方案,是的,错误就在那里,“修复”这个问题的唯一方法是强制我的应用程序重新连接到 oracle,所以这是我的示例

unless ActiveRecord::Base.connection.active?
  begin
    ActiveRecord::Base.connection.reconnect!
  rescue => e
    EchoServer.log e
  end
end

因此,在每次 Active Record 连接之前,我都会询问连接是否仍然存在,如果没有,我尝试手动重新连接,当时它正在工作,但是,这不是最佳解决方案,但是....希望它会起作用的

PD:有一些与此错误相关的问题,这里有几个:

https://github.com/rsim/oracle-enhanced/issues/420

reaper 是否与 oracle 增强型适配器 (OCI) 一起使用以获取空闲连接?

于 2014-04-23T02:30:16.533 回答