Какой тип MySQL лучше всего хранит информацию о времени - Datetime или Timestamp

0

Вступление

Я понимаю, что подобные вопросы были заданы здесь раньше. Но мне все еще нужно было немного больше испытать для моего случая использования - и я немного удивлен/смущен результатом.

Ниже приведено описание (с кодом) теста и результатов.

Я работаю над приложением, которое:

  • Записывает историю событий (вещи, которые произошли в определенный момент времени).
    • Эта история неизменна. Когда событие записывается, мы его не меняем.
    • Мы сообщаем об этой истории.
  • Расписание будущих, возможно повторяющихся действий. Например, "каждую пятницу делают эту проверку".

Поэтому очень важно четкое понимание временных данных.

Я пытаюсь понять типы timestamp в MySQL (datetime и timestamp) и как они взаимодействуют с Java-кодом и timestrings ISO8601.

Я прочитал документы MySQL по типу Timestamp - как он преобразует значение времени, чтобы сохранить его как UTC и, при извлечении, преобразует это значение UTC в зону времени сервера или сеанса. Это звучало как хорошее хранилище "точка-в-времени".

Тип MySQL datetime немного более непрозрачен. Эта статья (http://code.openark.org/blog/mysql/timestamp-vs-datetime-which-should-i-be-using) считает, что она не так сильно отличается от строки. Я повторил "SELECT NOW() + 0;" запрос и получил тот же ответ, что и статья.

Чтобы попытаться прояснить ситуацию, я написал небольшой класс Java, который написал одну таблицу базы данных, состоящую из 3 столбцов:

  • tz (строка, обозначающая стандартный идентификатор часового пояса). UTC использует тесты, но это не часовой пояс.
  • mydatetime (столбец Datetime)
  • mytimestamp (колонка отметки времени)

Код Java

Код Java находится здесь: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d

Тест 1

Я создал 3 разных строчки timestamp ISO8601 - все в один и тот же момент времени - но с разными смещениями/часовыми поясами. Каждый из них был записан в базу данных, извлечен и распечатан.

Для начала я установил часовой пояс сервера базы данных MySQL на "+00: 00".

Выход

Время написания базы данных.

UTC
2018-04-13T11:12:00Z, 1523617920
Europe/Amsterdam
2018-04-13T13:12:00+02:00, 1523617920
Asia/Calcutta
2018-04-13T16:42:00+05:30, 1523617920

Чтение сохраненных времен из базы данных.

Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523617920, 2018-04-13T11:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam],       1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta]

Все выглядит хорошо. Эпоха секунд, когда вставляется что-то вроде https://www.epochconverter.com/, согласуется со строками времени ISO8601.

Тест 2

Затем я изменил часовой пояс сервера MySQL с UTC (+00: 00) в Европу/Амстердам (+02: 00) и снова прочитал сохраненные моменты.

Выход

Чтение сохраненных времен из базы данных.

Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523625120, 2018-04-13T13:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523625120, 2018-04-13T15:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523625120, 2018-04-13T18:42+05:30[Asia/Calcutta]

Я ожидал, что столбец Datetime будет затронут - считая, что он не хранит информацию о часовом поясе. Тем не менее, это была колонка Timestamp, которая перемещалась.

Заключение

Мы не будем регулярно менять часовой пояс сервера. Я пытаюсь понять, какой тип данных MySQL лучше всего представляет собой момент времени - что-то, на что я могу рассчитывать, как точное и неизменное (а не разрушение головы). Исходя из вышесказанного, если я предоставляю информацию "точно в срок" в форме строки ISO8601, тип MySQL Datetime сохраняет предоставленную информацию.

Совершенно возможно, что мой тестовый код неверен и/или моя интерпретация результатов. Мог бы сделать с небольшим руководством здесь.

В приведенном выше тестовом примере тип Datetime MySQL лучше справляется с хранением информации о времени?

  • 0
    Большая проблема - это драйвер JDBC, и преобразования, которые он делает / пытается сделать для различий в часовых поясах, когда time_zone сеанса MySQL не соответствует JVM -Duser.timezone . С MySQL Connector / J, различные (на первый взгляд причудливые) поведения зависят от настроек useJDBCCompliantTimezoneShift , useLegacyDatetimeCode и serverTimezone И от обнаружения типов данных MySQL и сопоставления с типами данных JDBC ... строки и целые числа могут проходить через невредимые JB, но типы могут быть обмануты.
  • 0
    Также следует помнить о преобразованиях часовых поясов, которые происходят с MySQL, когда сеанс time_zone не соответствует серверному (глобальному) time_zone.
Показать ещё 4 комментария
Теги:
datetime
timestamp
iso8601

1 ответ

1

После немного более тонкой настройки я получил класс Java, который управляет хранением и получением информации о времени. Я все еще немного нервничаю по этому поводу - так много частей хотят сказать, что время, и это делает меня неудобным.

Класс находится в оригинальной форме: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d (и изменения показывают изменения).

  • Я могу изменить часовой пояс сервера MySQL на все, что пожелаю. Я все еще выхожу из того, что я вложил.
    • Также ведет себя запрос непосредственно в диспетчере запросов MySQL - столбец временной метки как unix-эпоха остается устойчивым. Это то, что я ожидаю.
    • выберите tz, mydatetime, unix_timestamp (mydatetime) как mydatetime_as_epoch, unix_timestamp (mytimestamp) из basic_time;
    • tz = идентификатор временной зоны (String); mydatetime (столбец Datetime); mytimestamp (колонка отметки времени)
  • Timestamp Тип MySQL - это метка времени. Мне не нужно возиться с этим.

    • Java 8 java.sql.Timestamp класс fromInstant и toInstant методы утверждают, что они поддерживают один и тот же момент времени.
    • Я пробовал Мгновенно на методах setObject и getObject prepareStatement. Соединитель MySQL/J просто не принимает их - я вникнул в исходный код для просмотра.
  • Datetime Тип MySQL Я все еще немного смущен (я не знаю, что это такое), но зная часовой пояс, я могу поддерживать информацию о времени.

  • Я попробовал как версии MySQL Connector/J 5.1.46, так и 8.0.11. Такое же поведение для каждого.
  • Параметр JDBC useLegacyDatetimeCode = false кажется важным. Мне нужно провести больше тестов с подтверждением и без этого.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню