1

我有模型来存储数据库连接参数(主机、数据库名称、用户名、密码)并按表格填写。在创建或更新之前,我需要检查输入参数的连接是否良好。我创建validate :check_connection验证器:

# don`t change primary connection
class Remote < ActiveRecord::Base; end

def check_connection
  return if errors.any? || (!new_record? && password.empty?)
  begin
    Remote.establish_connection(
      adapter: 'mysql2',
      host: host,
      username: username,
      password: password,
      database: database,
      connect_timeout: 5,
      reconnect: false
    )
    # maybe need to make some sql request? did try it
  rescue Exception => e
    errors.add :connection, 'Could not connect to database'
  end
end

当我尝试输入可访问主机 ( localhost) 时,上面的代码运行良好。但是,如果主机喜欢192.168.1.1(无法访问)页面在提交表单后冻结。我看到每秒都尝试连接,并且在浏览器上的 ESC(停止加载页面)之后它并没有停止(我看到网络接口上的 tcpdump 尝试)。尝试并没有停止..

那么,如何验证与数据库的连接?并且如果无法建立连接,页面一定不会长时间加载。

4

2 回答 2

0

变量connect_timeout是一个全局变量。因此,mysql2也许忽略它。

在 mysql5.6 上:

mysql[(none)]> set connect_timeout = 123;
ERROR 1229 (HY000): Variable 'connect_timeout' is a GLOBAL variable and should be set with SET GLOBAL

timeout在初始化 mysql2 时设置了变量,但没有反映。mysql2 的自述文件说您可以设置 *timeout 选项,但我认为自述文件已过时或损坏。

在 mysql2 0.3.14(gem) 上:

client =  Mysql2::Client.new(
  host: 'localhost',
  database: 'test',
  username: 'root',
  password: '',
  connect_timeout: 3,
  read_timeout: 3,
  write_timeout: 3,
  wait_timeout: 3);

client.query('show variables like "%timeout%"').map{|r| [r["Variable_name"], r["Value"]] }

=> [["connect_timeout", "10"],
 ["delayed_insert_timeout", "300"],
 ["innodb_lock_wait_timeout", "50"],
 ["innodb_rollback_on_timeout", "OFF"],
 ["interactive_timeout", "28800"],
 ["lock_wait_timeout", "31536000"],
 ["net_read_timeout", "30"],  # Maybe older mysql has read_timeout?
 ["net_write_timeout", "60"], # Maybe older mysql has write_timeout?
 ["slave_net_timeout", "3600"],
 ["wait_timeout", "28800"]]

如果使用ActiveRecord,则只能设置wait_timeout变量 by database.yml

在 database.yml 中:

development:
  adapter: mysql2
  encoding: utf8
  charset: utf8
  database: test
  pool: 5
  username: root
  password: 
  host: localhost
  connect_timeout: 3
  read_timeout: 3
  write_timeout: 3
  wait_timeout: 3

ActiveRecord 4.0.1 的结果:

> ActiveRecord::Base.connection.execute('show variables like "%timeout%"').to_a
=> [["connect_timeout", "10"],
 ["delayed_insert_timeout", "300"],
 ["innodb_flush_log_at_timeout", "1"],
 ["innodb_lock_wait_timeout", "50"],
 ["innodb_rollback_on_timeout", "OFF"],
 ["interactive_timeout", "28800"],
 ["lock_wait_timeout", "31536000"],
 ["net_read_timeout", "30"],
 ["net_write_timeout", "60"],
 ["rpl_stop_slave_timeout", "31536000"],
 ["slave_net_timeout", "3600"],
 ["wait_timeout", "3"]]

ActiveRecord 中设置wait_timeout变量abstract_mysql_adapter.rb

看:

abstract_mysql_adapter.rb https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapter/abstract_mysql_adapter.rb

mysql2_adapter.rb https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapter/mysql2_adapter.rb

于 2014-09-13T11:52:38.523 回答
0

我确实使用gem 'mysql2'并捆绑安装了 0.3.11 版本。此版本忽略connect_timeout并在较新版本中修复了错误。在我尝试 0.3.12b4 ( gem 'mysql2', '~> 0.3.12b4') 后一切正常。

于 2012-08-30T11:04:58.983 回答