согласование часовых поясов с SQL - PullRequest
0 голосов
/ 31 мая 2019

Вопрос 1/3:

У меня есть несколько MySQL баз данных для подключения, и я хочу обеспечить согласованность времени между запросами. Так, например, один из этих серверов в настоящее время находится в CDT часовом поясе.

> 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              |
+---------------------+--------------------+--------------------+---------------------+

Примечание. Сейчас мы находимся в DST, поэтому CDT. Я при условии, что это автоматически изменится на CST, когда выйдет за пределы DST, верно?

Итак, с учетом вышеизложенного, мой суффикс DSN выглядит примерно так:

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

Итак, есть ли в * 1020 программный способ сопоставить трехбуквенный код CDT с более формальными именами часовых поясов, такими как America/Chicago.

2/3:

Выше представлен сценарий «курица / яйцо»: для определения часового пояса удаленного сервера необходимо подключиться / запросить сервер; с этим знанием параметры DSN могут измениться для будущих вызовов.

Можно ли изменить параметры DSN по факту или необходимо создать новое соединение sql.DB пул соединений?

3/3

Вы можете спросить, зачем проверять, изменился ли часовой пояс - разве он не статичен? Что делать в ситуации с БД с балансировкой нагрузки? Теоретически две копии могут быть в разных часовых поясах?

Должны ли все столбцы с временными метками быть просто обернуты в SQL UNIX_TIMESTAMP(), чтобы нормализовать данные и избежать этой головной боли?

Я тоже мог бы попасть во времена, но сейчас остановлюсь.

1 Ответ

0 голосов
/ 08 июня 2019

1/3

go использует базу данных часовых поясов IANA с точными названиями зон. Попытка обратного инжиниринга того, как MySQL определяет формат локального часового пояса с хоста (Linux), и дублирование этой логики в go клиентах - как указал @MattJohnson - оказывается ненадежным.

2/3

database/sql.DB - созданный через Open(drv, DSN) - будет использовать тот же DSN для всех соединений. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1. 1018 *

3/3

Таким образом, лучше придерживаться MySQL для преобразования всех значений datetime из локального в часовой пояс UTC перед передачей клиенту. Это устраняет сложность установки часового пояса базы данных (возможно, неизвестного) во время соединения через DSN.

Один из многообещающих вариантов - установить часовой пояс сеанса соединения:

  • SET @@session.time_zone = "+00:00";
  • однако, это работает только для соединения current (в пределах пула соединений). Однако клиент go не будет знать, какое бесплатное соединение он может использовать в любое время.
  • Таким образом, чтобы убедиться, что это всегда работает, необходимо применить его вручную до всех запросов . Даже если используется только одно соединение с БД - если соединение не установлено и начинается повторная попытка соединения - любое предыдущее состояние сеанса будет потеряно.

Вместо этого, оборачивая все datatime столбцы с помощью функции преобразования, вот так:

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

гарантирует, что вычисление часового пояса выполняется во время запроса и не будет потеряно при переподключении соединения и т. Д.

Так что теперь DSN больше не нужно указывать loc - так как UTC является значением по умолчанию. На самом деле DSN нужен только суффикс опции ?parseTime=true, чтобы позволить datetime быть преобразованным в time.Time. *1058*.

Наконец, и самое главное, это будет работать с любым сервером, настроенным на любой часовой пояс.

H / T на этот ответ .

...