Ruby on Rails MySQL #08S01Bad handshake - downgrade MySQL? - mysql

We recently upgraded from MySQL 5.1.41 to 5.1.61 on our Ubuntu 10.04LTS server. We have an ancient RoR web app that's now giving a bad handshake error:
Mysql::Error in MainController#index
#08S01Bad handshake
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/vendor/mysql.rb:523:in `read'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/vendor/mysql.rb:153:in `real_connect'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:389:in `connect'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:152:in `initialize'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:82:in `new'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:82:in `mysql_connection'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb:262:in `send'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb:262:in `connection_without_query_cache='
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/query_cache.rb:54:in `connection='
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb:230:in `retrieve_connection'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb:78:in `connection'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:763:in `columns'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:2060:in `attributes_from_column_definition_without_lock'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/locking/optimistic.rb:45:in `attributes_from_column_definition'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1502:in `initialize_without_callbacks'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/callbacks.rb:225:in `initialize'
#{RAILS_ROOT}/app/controllers/application.rb:48:in `new'
#{RAILS_ROOT}/app/controllers/application.rb:48:in `log_info'
/usr/local/bin/mongrel_rails:19:in `load'
/usr/local/bin/mongrel_rails:19
I googled around and stumbled onto http://bugs.ruby-lang.org/issues/5017 which tells me it's a Ruby MySQL extension bug. We aren't using the MySQL gem. Our web app is incredibly old and fragile (Ruby v1.8.7, Rails v1.2.3, Mongrel 1.1.5). We're in the process of replacing it with a Django rewrite, so we just need to get this functional for the next few weeks until we will replace it with the new site.
How can we get past this error? I'm thinking that downgrading to MySQL 5.1.41 is the best way to handle this, and then when we begin using the new site in a few weeks, we can re-upgrade to 5.1.61. However, I'm having an issue downgrading mysql. This is the command I'm using:
sudo aptitude install mysql-server-5.1=5.1.41-3ubuntu12.10
However, this tells me Unable to find a version "5.1.41-3ubuntu12.10" for the package "mysql-server-5.1". I've tried sudo aptitude install mysql-server-5.1=5.1.41 also, but that didn't work either. How can I have aptitude install the correct version of MySQL?

Instead of downgrade MySQL gem, it's possible to fix the database name parameter to fix the "bad handshake" problem.
I found this: https://github.com/rubygems/rubygems/issues/423 It's working good.
Instead of doing a hack in real_connect it's possible to add the "\0" in config/database.yml
production:
database: "itsalive_production\0"
adapter: mysql
host: localhost
encoding: UTF8
...
EDIT
If you use the solution with \0 at the end of the database name. You probably will find find out this and solve it yourself, but I mention it anyway:
(at least in my version of Rails)
Using the database string with \0 at the end gives problem when doing rake test. It starts with deleting the test database before copying the development database definitions, and then using a SQL command string that includes the test database name. This will cause an error because of the \0 in the middle of the string.
In my case I'm using a local development database that doesn't give any problem so I don't need to have \0 in that name.
Here is a alternative hack to solve that (original code in mysql_adapter.rb):
module ActiveRecord
module ConnectionAdapters
class MysqlAdapter
alias_method :old_execute, :execute
def execute(sql, name = nil) #:nodoc:
# This is needed because database names can end with "\0" to fix
# the issue with "handshake" when mysql server is newer than the gem
# requires. E.g. called when loading the new test db when doing "rake test".
sql = sql.delete("\0")
old_execute(sql, name)
end
end
end
end

I fixed it! Downgrading MySQL did the trick. We'll re-upgrade to 5.1.61 once the Django site goes live. Here's the command to downgrade MySQL:
sudo aptitude install mysql-server-5.1=5.1.41-3ubuntu12 mysql-client-5.1=5.1.41-3ubuntu12 mysql-server-core-5.1=5.1.41-3ubuntu12
I used apt-cache to get the exact version.

I also had the same issue. Please add:
config.gem 'mysql', :version => '2.7'
Then run rake gems:install.

Related

Mysql2::Error: # MySQL client is not connected — Rails 6.0.2.2 with rspec; Ruby 2.6.4 mac os Catalina + Mojave

I'm getting this extremely strange intermittent problem with MySQL on Rails 6.0.2.2,
RSpec 4.0.0.rc1,
Ruby 2.6.4
on a two separate Macs, one is running macOS Mojave and the other is running MacOS Catalina
Interestingly, the mac running Catalina appears to do it less often, although it still does this. the failure is intermittent, seems to happen immediately after another failure in the suite, but then often continues to show up (across about half of the test suite) on subsequent runs, even if I've fixed the originally failing spec.
1) Template
Failure/Error: _query(sql, #query_options.merge(options))
ActiveRecord::StatementInvalid:
Mysql2::Error: MySQL client is not connected
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `block in query'
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `handle_interrupt'
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `query'
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Mysql2::Error:
# MySQL client is not connected
# /Users/jason/.rvm/gems/ruby-2.6.4/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
I began having this problem when I set up my personal laptop (Mac OS Catalina) to do work from home. In the process, I updated our environment from Ruby 2.4.7 to 2.6.3 and gems system from 3.0.6 to 3.1.2. And, no doubt, incremental updates to our bundled gems also happened. I have not been able to identify which change resulted in the new, seemingly random and intermittent failures.
Google led me here first, and second to this discussion on a minitest issue:
https://github.com/seattlerb/minitest/issues/744
Then, looking closer at my tests, I noticed that the first test to fail always triggered an async method.
I added this to my config/environments/test.rb file:
config.active_job.queue_adapter = :inline
And all tests are passing again.
I don't know if this constitutes a fix or a work around. I'm not sure if asynchronous processes were working before or if they were previously being handled inline and a default behavior changed. The tests we currently have aren't specifically validating asynchronicity. So, for the moment, this solved my problem.
In my case I had issues while running tests for ActiveJob background jobs, and
adding config.active_job.queue_adapter = :test to config/environments/test.rb worked for me.

NameError: cannot load Java class com.mysql.jdbc.Driver

I'm using JRuby 1.7.2, along with DataMapper, and I'm getting an error I can't find an answer to.
I'm just testing out DataMapper along with MySQL 5.5 to see if it will run fine when I build around it. Here's the file I'm testing:
require "data_mapper"
require "keys"
DataMapper.setup(:default, "mysql://#{$user}:#{$pass}#localhost/test_db")
And when I run this, I get the error:
NameError: cannot load Java class com.mysql.jdbc.Driver
And it points to the DataMapper.setup line.
My Gemfile should be alright:
source :rubygems
gem "sinatra"
gem "trinidad"
gem "data_mapper"
# do a `sudo apt-get install libmysqlclient-dev` first
gem "dm-mysql-adapter"
gem "jdbc-mysql"
Is there anything I'm missing? I have MySQL set up with a user/pass locally already.
This is a common error when running JDBC clients for MySQL. You need to make sure you have mysql-connector-java-bin.jar on the classpath. You can download it from here.
I'm using Rails 3.2.9 and to solve the problem I added this to my application.rb
if defined? JRUBY_VERSION
require 'jdbc/mysql'
Jdbc::MySQL.load_driver
end
actually, the correct answer is to work-around an incompatibility between 5.1.13 and 5.1.22 !
jdbc-mysql gem already contains the mysql-connector.jar it just ain't auto-loading anymore :
https://github.com/jruby/activerecord-jdbc-adapter/tree/master/jdbc-mysql (read the README)
you can also force the driver to auto-load using a Java system property e.g. from a cmd line :
jruby -J-Darjdbc.mysql.autoload=true -S rake ...
I had the same error when trying to use a mysql database from jruby/rails4. In my case this line was missing from ./Gemfile:
gem 'jdbc-mysql'

Standalone script reports "MySQL server has gone away"; problem with my.cnf?

I have a ruby script that requires 'mysql2' and uses query statements to mysql like
#db.query("SELECT sname,id FROM streets where region_id=#{region["id"]}")
but it reports me a error always like this:
main.rb:261:in `query': MySQL server has gone away (Mysql2::Error)
from main.rb:261:in `block (3 levels) in <main>'
from main.rb:258:in `each'
from main.rb:258:in `block (2 levels) in <main>'
from main.rb:254:in `each'
from main.rb:254:in `block in <main>'
from main.rb:253:in `loop'
from main.rb:253:in `<main>'
The script on my Ubuntu is OK, however, my production environment is CentOS and on there I installed MySQL from source code. My Rails app run there is OK and it also requires 'mysql2', but when I run this script it fails.
I think the problem is related to my.cnf but I don't know how configure it.
The mysql2 gem provides an option to reconnect to MySQL in the event that the connection goes away. Rather than updating your my.cnf file, update your gem's database.yml file to include the
reconnect: true
option. This will ensure that the mysql2 gem will attempt to reconnect to MySQL when required.
you call .query method directly on object #db... what exactly is this object?
I mean... if you are under Rails, you should call queries like:
result = ActiveRecord::Base.connection.execute("sql here")
I think it could be the cause, because Rails manages connection pool (eg. 5 established connections and every query goes to one of them, based on requests).
Anyway, if this is not the cause, then it can be that your mysql2 gem is compiled with different version of libmysqlclient.so library on the system...
Then when you try to do a query, it internally throws an error about incompatible protocol and disconnects...
Please check that your libmysqlclient.so and it's header files are of the same version...
Or if you don't have more versions of them installed...
and then please try to recompile mysql2 gem.
Hope this helps.
Regards, NoICE

Rails keeps trying to use SQLite , despite that I've configured MySQL for my project

I setup my rails project "tracks" using:
$ rails --database=mysql tracks # OK
$ cd tracks
$ vim config/database.yml # correct using mysql adapter, added password spec
$ rake db:create RAILS_ENV='development' # OK
$ rake db:migrate # OK
$ ruby script/generate scaffold user name:string password:string email:string url:string # OK
$ rake db:migrate # OK, creates table
$ ruby script/server # OK, starts WEBrick
I open up the thing in a web browser:
http://localhost:3000 # correctly shows the rails welcome splash
I navigate to
http://localhost:3000/users/new
and get a huge slew of errors:
ActiveRecord::StatementInvalid in UsersController#index
SQLite3::SQLException: no such table: users: SELECT * FROM "users"
RAILS_ROOT: /home/drew/tracks/trunk/tracks
Application Trace | Framework Trace | Full Trace
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:188:in `log'
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute'
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:372:in `catch_schema_changes'
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute'
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:275:in `select'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:60:in `select_all'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:81:in `cache_sql'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:60:in `select_all'
vendor/rails/activerecord/lib/active_record/base.rb:635:in `find_by_sql'
vendor/rails/activerecord/lib/active_record/base.rb:1490:in `find_every'
vendor/rails/activerecord/lib/active_record/base.rb:589:in `find'
app/controllers/users_controller.rb:5:in `index'
wtf? Why is ruby still trying to use SQLite? database.yml has zero mention of SQLite.
Thanks
Couldn't figure it out. I ended up reinstalling the OS on the VM and trying again and it worked.
FYI: Do not install rubygems from a package manager like apt-get. Compile it from source or it will all end in tears.
Had this problem, I found all of the files using "find . | xargs grep 'sqlite3' -sl then replaced all of the yml and rb files it found then restarted the server.
Unfortunately, I don't know which (if any, as it may have been the server restart) solved the issue, but now I'm on and up.
Hope that helps someone, however 'hacky'.
Quick Fix that i've used is...
When i start a project a specify the -d for database
rails -d mysql ProjectName
Which builds the database.yml file for mysql
hope this helps.
As odd as it might sound, try clearing your browser's cookies. I had a similar problem moving from sqlite to postgresql and vice versa. It turns out the stored cookie or session was somehow making the server get stuck in using the old database. If this works then you'll want to take steps on your server to invalidate any existing cookies in your users' browsers.
Don't mean to necro, but if someone runs onto this problem, edit your config/database.yml file, and remove the line that says << default from the production section. What this is doing is loading the default environment first, so Passenger loads it instead of whatever else you've configured.

Multiple MySQL queries with Ruby

I'm having troubles with MySQL queries in Ruby. I use 'mysql' gem.
Configuration is stored in a separate yml file and loaded into #conf variable.
This is my code:
# connect to the database
Mysql::new(#conf['sql_host'], #conf['sql_user'], #conf['sql_password'], #conf['sql_base'])
# it's ok when we're doing this
my.query("SELECT * FROM `my_table`") do |e|
# code
end
# Maybe, I've missed something here...
# really this query will insert value into other table, used SELECT just for testing
# this throws exception: 'query: not connected'
my.query("SELECT * FROM `my_table_2`")
Windows XP
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]
mysql (2.8.1, 2.7.3)
MySQL client version: 5.0.51a
Second query throws 'query: not connected'.
First of all, your program looks ok. I am 100% sure you have libmysql.dll version problem.
I can reproduce this with libmysql.dll provided from Mysql installer.
Download this file and replace in c:\ruby\bin\
http://instantrails.rubyforge.org/svn/trunk/InstantRails-win/InstantRails/mysql/bin/libmySQL.dll
and re-run your program without any change.
Related issue and credit to here
I have run into immeasurable problems when attempting to use Ruby's mysql gem on any version of Windows. From what I can tell, it simply doesn't work unless you can figure out how to compile it yourself (which is a royal pain in the ass).
Have you considered using ActiveRecord as your ORM (object relational mapping) layer and doing development with SQLite or some other database on Windows and then running the production environment on Linux with MySQL? This is the solution that I took a while back and it worked out quite well.