我有模型来存储数据库连接参数(主机,数据库名称,用户名,密码)并按表单填写。在创建或更新之前,我需要检查连接是否与输入的参数一致。我创建了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)。尝试并没有停止..
那么,如何验证与数据库的连接?如果无法建立连接页面必须不会加载很长时间。
答案 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