检查mysql与远程主机的连接

时间:2012-08-30 08:38:14

标签: mysql ruby-on-rails validation activerecord model

我有模型来存储数据库连接参数(主机,数据库名称,用户名,密码)并按表单填写。在创建或更新之前,我需要检查连接是否与输入的参数一致。我创建了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)。尝试并没有停止..

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

变量connect_timeout是一个全局变量。因此,mysql2可能会忽略它。

on 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

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

on 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设置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_adapters/abstract_mysql_adapter.rb

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