-1

Question 1/3:

I have a number of MySQL databases to connect to and want to ensure time consistency across queries. So for example, one of these servers is currently in the CDT timezone.

> select CURRENT_TIMESTAMP, @@system_time_zone, @@global.time_zone, @@session.time_zone;

+---------------------+--------------------+--------------------+---------------------+
| CURRENT_TIMESTAMP   | @@system_time_zone | @@global.time_zone | @@session.time_zone |
+---------------------+--------------------+--------------------+---------------------+
| 2019-05-31 09:44:45 | CDT                | SYSTEM             | SYSTEM              |
+---------------------+--------------------+--------------------+---------------------+

Note: We're in DST right now, so it's CDT. I'm assuming this would automatically change to CST when outside DST, right?

So with the above knowledge, my DSN suffix looks something like this:

...?parseTime=true&loc=America%2FChicago // i.e. 'America/Chicago' - maybe 'CST6CDT' would work too?

So, is there a programatic way in go to map from the 3-letter code CDT to the more formal timezone names like America/Chicago.

2/3:

The above presents a chicken/egg scenario: in order to determine the remote server's timezone, one needs to connect/query the server; with that knowledge the DSN parameters may change for future calls.

Can DSN parameters be changed after the fact, or does a brand new connection sql.DB connection pool need to be created?

3/3:

You may ask, why check to see if the timezone has changed - isn't it static? What should one do in a Load-Balanced DB situation? Two replicas could in theory be in differing timezones?

Should all columns with timestamps just be wrapped with an SQL UNIX_TIMESTAMP() to normalize the data and avoid this headache?

I could get into time-drifts too, but I'll stop here for now.

colm.anseo
  • 19,337
  • 4
  • 43
  • 52
  • The system time zone should `America/Chicago`. If it's `CDT`, it's likely set wrong on the system. What OS is the system anyway? – Matt Johnson-Pint Jun 01 '19 at 06:11
  • Keep in mind that time zone abbreviations can sometimes be derived from time zone identifiers, but not usually the other way around. There's just too much ambiguity. The C in CST could just as well be for China or Cuba. – Matt Johnson-Pint Jun 01 '19 at 06:13
  • @MattJohnson yep - that's the conclusion I came to also. Rather than reverse engineer how MySQL reports the timezone, the simplest approach was to normalize the time from within the SQL query, so `go` would get UTC times and thus not need to be converted. – colm.anseo Jul 03 '19 at 18:36

1 Answers1

0

1/3

go uses IANA's Time Zone Database with precise zone names. Trying to reverse engineer how MySQL determines the local timezone format from a (Linux) host and duplicate that logic in a go clients - as @MattJohnson pointed out - proves to be unreliable.

2/3

database/sql.DB - created via Open(drv, DSN) - will use the same DSN for all connections. While an sql.DB is meant to be created once and used many times - there is no way to change the DSN after the fact - so one would need to create a brand new sql.DB when changing the DSN.

3/3

So the better tack, appears to leverage MySQL to convert all datetime values from local to UTC timezone before transmission to the client. This removes the complication of setting the database's (possibly unknown) timezone at connection time via the DSN.

One promising option, is to set the connection's session timezone:

  • SET @@session.time_zone = "+00:00";
  • however, this only works for the current connection (within the connection pool). A go client however will not know which free connection they may be using at any give time.
  • So to ensure this always works, one would need to apply it manually before all queries. Even if only one DB connection is in use - if the connection fails and connection retry kicks in - any previous session state would be lost.

So instead, wrapping all datatime columns with a conversion function like so:

CONVERT_TZ(`STAMP_UPDATED`,@@session.time_zone,'+00:00')

ensures the timezone calculation is done at query time and will not be lost during a connection reconnection etc.

So now the DSN no longer needs to specify loc - as UTC is the default. In fact the DSN only needs the suffix option of ?parseTime=true to allow the datetime to be translated into go's native time.Time.

Finally and most importantly, this will work with any server set to any timezone.

H/T to this answer.

colm.anseo
  • 19,337
  • 4
  • 43
  • 52