написать впереди
Недавно в своей работе я столкнулся с двумя проблемами, связанными с временными метками mysql: во-первых, точность mysql-connector-java и msyql несовместима, что приводит к тому, что данные не могут быть найдены, во-вторых, ошибка часового пояса сервера приложений приводит к тому, что данные чтобы не допрашивали. В этой статье я надеюсь ответить на несколько вопросов о временных метках в mysql:
- Почему точность DATETIME в mysql поддерживается только в секундах?
- Связан ли тип DATETIME в mysql с часовым поясом?
- Когда mysql создает таблицу, как выбрать поле, представляющее время?
Пример проблемы с точностью DATETIME
Некоторое время назад версия mysql-connector-java ответственного приложения была обновлена с 5.1.16 до 5.1.30.При выполнении функциональной регрессии было обнаружено, что данные времени выполнения вариантов использования с использованием SQL, аналогичные приведенным выше, будут отсутствует, что приводит к возникновению проблемы с функцией.
Учитывая, что в приложении, за которое я отвечаю, есть функция, которая должна использовать SQL, как показано ниже, то есть использовать метку времени в качестве условия запроса для запроса всех данных после определенной метки времени.
После расследования было обнаружено, что: mysql-connector-java отбрасывает точность после секунды, прежде чем передать ее на сервер MySQL до 5.1.23. Бывает, что точность DATETIME в используемой нами версии mysql составляет секунды; когда я обновить mysql-connector-java После 5.1.30, когда метка времени передается из приложения java на сервер MySQL через mysql-connector-java, миллисекунды не будут отброшены.С точки зрения mysql-connector-java, ошибка был исправлен, но для моего приложения это вызвало ошибку.
Если вы столкнетесь с этой проблемой, как вы ее исправите?
В то время мы думали о трех вариантах:
-
Измените тип параметра timestamp в интерфейсе Mapper mybatis с java.util.Date на java.sql.Date;
-
Перед переходом в интерфейс Mapper входящая метка времени положительна в секундах, код выглядит следующим образом
-
Перед запросом уменьшите входящую метку времени на 1 секунду;
После проверки схема 1 будет, объект java.sql.Date, переданный java.util.Date, потеряет всю точность после даты, что приведет к запросу большего количества ненужных данных; схема 3 возможна, но может быть или еще два данных, возможна и схема 2, что равносильно компенсации характеристик mysql-connector-java из кода. В итоге выбрал вариант 2.
Повторение случая
Используйте homebrew для установки MySQL, версия 8.0.15.После установки создайте таблицу для хранения информации о пользователе.SQL выглядит следующим образом:
Используйте spirngboot + mybatis в качестве среды разработки, определите пользовательскую сущность, код выглядит следующим образом:
Определите Mapper, соответствующий объекту, код выглядит следующим образом:
Установите конфигурацию, связанную с подключением к mysql, код выглядит следующим образом:
Напишите тестовый код, сначала вставьте часть данных, а затем используйте метку времени в качестве условия запроса для запроса, код выглядит следующим образом:
Запуск одного теста, как мы предполагали, не запрашивал данные, и результаты следующие:
Затем измените код и используйте приведенный выше код, чтобы сделать отметку времени запроса положительной в секундах.Код выглядит следующим образом:
Запустите одиночный тест еще раз, как мы и предполагали, на этот раз данные можно запросить.
Однако вот небольшой эпизод: когда я впервые проектировал таблицу, оператор SQL, который я использовал, был следующим:
Как бы вы ни были умны, здесь datetime уже поддерживает меньшую точность времени после десятичной точки и поддерживает до 6 цифр, то есть может поддерживать до тонкого уровня. Когда была представлена эта функция?Я проверил [официальную документацию MySQL][9] и обнаружил, что эта функция поддерживается после MySQL 5.6.4.
Резюме очков знаний
После предыдущего фактического анализа случая и повторения случая читатель должен иметь определенное представление о типе DATETIME в mysql.Давайте посмотрим на него со мной и какой опыт мы можем извлечь из этого случая.
- Версию mysql-connector-java и версию mysql необходимо использовать вместе, например версию до 5.6.4, лучше не использовать версию mysql-connector-java после 5.1.23, иначе на этот раз мы можем столкнуться с возникшими проблемами.
- Типы полей, используемые для представления времени в MySQL: DATE, DATETIME, TIMESTAMP. Они имеют сходство, и каждый из них имеет свои характеристики. Я резюмирую таблицу следующим образом:
- Тип DATETIME хранится как целое число в формате «ГГГГММДДЧЧММСС» в MySQL, независимо от часового пояса, и занимает 8 байтов пространства;
- Тип TIMESTAMP может сохранить гораздо меньший временной диапазон, а отображаемое значение зависит от часового пояса.Сервер MySQL, операционная система и клиентское соединение имеют настройки часового пояса.
- Как правило, рекомендуется использовать DATETIME в качестве поля метки времени, и не рекомендуется использовать тип bigint для хранения времени.
- При разработке следует стараться избегать использования временных меток в качестве условий запроса.Если вы должны их использовать, вам необходимо полностью учитывать точность MySQL и точность параметров запроса.
использованная литература
- Dev.MySQL.com/doc/Furious/…
- «Высокопроизводительный MySQL»
В этом выпуске основное внимание уделяется таким темам, как серверные технологии, устранение неполадок и оптимизация JVM, вопросы на собеседованиях по Java, личностный рост и самоуправление, а читателям предлагается опыт работы и роста передовых разработчиков. .