2012-08-30 164 views
1

我有模型来存储数据库连接参数(主机,数据库名称,用户名,密码)并填写它的形式。在创建或更新之前,我需要检查连接是否适合输入的参数。我创建validate :check_connection验证:检查mysql连接到远程主机

# 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(无法访问)页面冻结后提交表单。我看到每秒连接的尝试,并且它在浏览器(停止加载页面)后不停止(我在网络接口上看到tcpdump的尝试)。并尝试不停止。

那么,我该如何验证连接到数据库?而如果连接不能建立,页面必须不会加载很长时间。

+0

我尝试在轨控制台'Mysql2 :: Client.new(主持人: '192.168.1.1',数据库: 'test',用户名:'user',密码:'pass',connect_timeout:1,read_timeout:1,write_timeout:1)'并且永久尝试连接。超时不起作用。哪里不对? –

回答

0

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

+0

phew,一年后,0.3.12还没有发布还是:( – Kevin

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自述文件说,你可以设置*超时选项,但我认为自述文件已过时或损坏。

上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,您可以通过设置database.ymlwait_timeout变量。

在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