Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Set Session Time Zone While Connecting to Mysql #13663

Open
wants to merge 2 commits into from

2 participants

@azitabh

Mysql sets the time zone for all the connections as SYSTEM which is the time zone of the system where mysql-server is running. In my case it is +05:30. It stores all the values in UTC while it accepts and returns all values in the timezone set as session time_zone.

Default timezone for rails4 is :local whereas AR default for rails4 is UTC . So when I set a timestamp field by doing Time.now, AR converts the time into UTC and sends it to Mysql. Mysql assumes the incoming value to be in +05:30 and hence converts it to UTC before storing. So, the conversion to UTC is happening twice.

This problem can be solved by letting AR know what Mysql session time_zone is.
config.active_record.default_timezone = :local

But the problem is if mysql server is to be moved to a separate machine with different time zone setting, our rails application needs to aware of this change and config.active_record.default_timezone must be changed accordingly for a consistent behavior.

This dependency can be removed if AR sets the session time_zone to whatever is set as config.active_record.default_timezone while connecting to the mysql server.
It can be done at the same time when AR sets variables like wait_timeout and etc.

Please point out if I am missing something.

@dmathieu
Collaborator

Could you add tests please?

@azitabh

@dmathieu : I have added test cases. Please have a look.

@azitabh

Test case is failing with the following message:
I, [2014-01-12T19:00:28.467472 #17019] INFO -- : localhost:11211 failed (count: 1) Timeout::Error: execution expired
W, [2014-01-12T19:00:28.467574 #17019] WARN -- : localhost:11211 is down

Any help why did this happen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 10, 2014
  1. @azitabh
Commits on Jan 12, 2014
  1. @azitabh
This page is out of date. Refresh to see the latest.
View
6 activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -747,6 +747,12 @@ def configure_connection
# Turn this off. http://dev.rubyonrails.org/ticket/6778
variables[:sql_auto_is_null] = 0
+ if ActiveRecord::Base.default_timezone.eql?:utc
+ variables[:time_zone] = '+00:00'
+ else
+ variables[:time_zone] = DateTime.now.zone
+ end
+
# Increase timeout so the server doesn't disconnect us.
wait_timeout = @config[:wait_timeout]
wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
View
32 activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -33,6 +33,38 @@ def test_no_automatic_reconnection_after_timeout
end
end
+ def test_session_timezone
+ original_timezone = ActiveRecord::Base.default_timezone
+ global_mysql_timezones = []
+
+ # checking session timezone while the config value is :utc
+ ActiveRecord::Base.default_timezone = :utc
+ @connection.reconnect!
+ session_mysql_timezone = @connection.exec_query "SELECT @@SESSION.time_zone"
+ global_mysql_timezones << @connection.exec_query("SELECT @@GLOBAL.time_zone").rows[0]
+ assert_equal [["+00:00"]], session_mysql_timezone.rows, "Session time_zone not set correctly."
+
+ # checking session timezone while the config value is :local
+ ActiveRecord::Base.default_timezone = :local
+ @connection.reconnect!
+ session_mysql_timezone = @connection.exec_query "SELECT @@SESSION.time_zone"
+ global_mysql_timezones << @connection.exec_query("SELECT @@GLOBAL.time_zone").rows[0]
+ assert_equal [[DateTime.now.zone]], session_mysql_timezone.rows, "Session time_zone not set correctly."
+
+ # checking session timezone while the config value is otherwise
+ ActiveRecord::Base.default_timezone = ''
+ @connection.reconnect!
+ session_mysql_timezone = @connection.exec_query "SELECT @@SESSION.time_zone"
+ global_mysql_timezones << @connection.exec_query("SELECT @@GLOBAL.time_zone").rows[0]
+ assert_equal [[DateTime.now.zone]], session_mysql_timezone.rows, "Session time_zone not set correctly."
+
+ # global value should remain unaffected
+ assert_equal 1, global_mysql_timezones.uniq.count, "Global mysql time_zone shouldn't change."
+
+ ActiveRecord::Base.default_timezone = original_timezone
+ @connection.reconnect!
+ end
+
def test_successful_reconnection_after_timeout_with_manual_reconnect
assert @connection.active?
@connection.update('set @@wait_timeout=1')
Something went wrong with that request. Please try again.