Летнее время и системный часовой пояс в MySQL
Март - это не только месяц, когда пандемия закрыла все границы, и людям пришлось оставаться дома на карантине; это также месяц, когда происходит переход на летнее время. Для некоторых регионов это не только изменение времени, но и переход на другой часовой пояс. Например, Нью-Йорк использует EST зимой и EDT летом. Если вы используете системный часовой пояс и не перезапускаете сервер MySQL или узел PXC после переключения, вы можете заметить, что изменение не было реализовано.
Вы можете столкнуться с ситуацией, когда некоторые узлы вашего кластера все еще используют часовой пояс до переключения (например, EST), а другие используют часовой пояс после изменения (например, EDT).
$ date
Sun Mar 8 03:03:28 EDT 2020
$ ./bin/mysql -h127.0.0.1 -P3373 -uroot test
...
EDT node> show variables like '%zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | EDT |
| time_zone | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)
$ ./bin/mysql -h127.0.0.1 -P3372 -uroot test
...
EST node> show variables like '%zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | EST |
| time_zone | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)
Стоит ли беспокоиться об этом?
Нет!
MySQL инициирует переменную system_time_zone при ее запуске. Даже если переменная содержит данные с задержкой, все вычисления выполняются правильно, а временные значения уже используют новый часовой пояс.
Чтобы продемонстрировать это, давайте посмотрим на простую таблицу, содержащую значения меток времени:
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
Во-первых, давайте проверим существующие данные; это независимо от того, какое значение переменной system_time_zone использует node:
EDT node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
+----+---------------------+
3 rows in set (0.00 sec)
EST node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
+----+---------------------+
3 rows in set (0.00 sec)
Если мы добавим новую строку, допустимая временная метка будет вставлена на оба node:
EST node> insert into t1 values();
Query OK, 1 row affected (0.01 sec)
EST node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
| 8 | 2020-03-08 03:02:22 |
+----+---------------------+
4 rows in set (0.00 sec)
EDT node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
| 8 | 2020-03-08 03:02:22 |
+----+---------------------+
4 rows in set (0.00 sec)
Как видите, строка, вставленная в node, запущенная до изменения часового пояса, имеет одинаковое значение на обоих нодах.
То же самое происходит, если мы вставляем новую строку в node, запущенную после изменения времени:
EDT node> insert into t1 values();
Query OK, 1 row affected (0.01 sec)
EDT node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
| 8 | 2020-03-08 03:02:22 |
| 9 | 2020-03-08 03:02:32 |
+----+---------------------+
5 rows in set (0.00 sec)
EST node> select * from t1;
+----+---------------------+
| id | ts |
+----+---------------------+
| 2 | 2020-03-08 01:03:53 |
| 4 | 2020-03-08 01:03:54 |
| 6 | 2020-03-08 01:03:55 |
| 8 | 2020-03-08 03:02:22 |
| 9 | 2020-03-08 03:02:32 |
+----+---------------------+
5 rows in set (0.00 sec)
Вывод
Если вы используете time_zone = SYSTEM , вы можете заметить, что значение переменной system_time_zone устарело после изменения летнего времени. Но вам не стоит об этом беспокоиться, потому что все расчеты будут использовать обновленное время.