Rails 2.2.2性能问题/错误

时间:2009-02-01 19:17:45

标签: mysql ruby-on-rails performance debugging

我最近将我的一个应用程序升级到Rails 2.2.2。完成后,我遇到了一个奇怪的性能错误,导致渲染过去几分钟内完成,最多需要10秒钟。

我已经分析了这个问题,here are the results I've come up with。看起来问题出在Mysql类的real_connect方法中。我的理解是Ruby real_connect方法是C mysql_real_connect()函数的包装器。这会让我相信问题必须在数据库中,因为我在Windows和Linux上运行代码时遇到了同样的问题(数据库服务器是一个单独的系统)。但是,我不相信这种情况,因为当我从我的subversion存储库回滚到以前的版本(pre Rails 2.2.2)时,性能问题就消失了。这似乎表明ActiveRecord中存在某种错误。

如何识别和修复此错误?有没有人有任何见解?有什么我想念的吗?

更新:我刚刚创建了一个小的探查器脚本来测试Mysql.real_connect方法,看起来问题不在Rails中,而是在MySQL gem或数据库服务器本身。

运行以下代码:

result = RubyProf.profile do
  5.times do
    begin
     # connect to the MySQL server
     dbh = Mysql.real_connect(ip, user, pass, db)
     # get server version string and display it
     puts "Server version: " + dbh.get_server_info
    rescue Mysql::Error => e
     puts "Error code: #{e.errno}"
     puts "Error message: #{e.error}"
     puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
    ensure
     # disconnect from server
     dbh.close if dbh
    end
  end
end

printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT, 0)

我想出了这个表现结果:

Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Thread ID: 18998180
Total: 50.402000

 %self     total     self     wait    child    calls  name
 99.99     50.40    50.40     0.00     0.00        5  <Class::Mysql>#real_connect (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00       10  IO#write (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Mysql#get_server_info (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Kernel#puts (ruby_runtime: 0}
  0.00      0.00     0.00     0.00     0.00        5  String#+ (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Mysql#initialize (ruby_runtime:0}
  0.00     50.40     0.00     0.00    50.40        1  Integer#times (ruby_runtime:0}
  0.00     50.40     0.00     0.00    50.40        1  Global#[No method] (tmp/mysql_test/test.rb:12}
  0.00      0.00     0.00     0.00     0.00        5  Mysql#close (ruby_runtime: 0}

好像问题不在ActiveRecord中,它可能在MySQL gem或数据库中。我从哪里开始?

1 个答案:

答案 0 :(得分:1)

我能够找到问题所在。我首先使用命令mysql --host=ip --user=user --password=password db使用我的开发机器上的MySQL命令连接到主机。这非常慢,所以我进入服务器,并使用相同的命令从那里连接。这也很慢。

我将命令更改为mysql --host=localhost --user=user --password=password db,我能够即时连接。我在/etc/hosts文件中为我的开发系统添加了一个条目,并且能够即时连接。显然,MySQL服务器正在尝试执行反向dns查找以解析与IP地址关联的主机名,如MySQL Manual中所列,并且已超时。

我将--skip-name-resolve选项添加到/etc/init.d/mysql脚本的start部分,以便跳过此检查,然后重新启动服务器。当我运行之前创建的配置文件脚本时,我得到以下结果:

Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Thread ID: 52978590
Total: 0.016000

 %self     total     self     wait    child    calls  name
 87.50      0.01     0.01     0.00     0.00        5  <Class::Mysql>#real_connect (ruby_runtime:0}
  6.25      0.00     0.00     0.00     0.00       10  IO#write (ruby_runtime:0}
  6.25      0.00     0.00     0.00     0.00        5  Mysql#close (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Kernel#puts (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Mysql#initialize (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  String#+ (ruby_runtime:0}
  0.00      0.02     0.00     0.00     0.02        1  Global#[No method] (tmp/mysql_test/test.rb:12}
  0.00      0.02     0.00     0.00     0.02        1  Integer#times (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        5  Mysql#get_server_info (ruby_runtime:0}