MySQL のタイムスタンプと日付時刻のタイムゾーンの問題によって生じる DTS の落とし穴の詳細な説明

MySQL のタイムスタンプと日付時刻のタイムゾーンの問題によって生じる DTS の落とし穴の詳細な説明

MySQL で現在の時刻を表現するにはどうすればよいでしょうか?

実際、表現方法はいろいろありますが、まとめると次のようになります。

データタイプ「ゼロ」値
DATE '0000-00-00'
TIME '00:00:00'
DATETIME '0000-00-00 00:00:00'
TIMESTAMP '0000-00-00 00:00:00'
YEAR 0000

datetime 型と timestamp 型はどちらも、YYYY-MM-DD HH:MM:SS の形式でデータを表すために使用されますが、両者にはいくつかの違いがあります。

結論は

  • timestamp は実際には 1970-01-01 00:00:00 UTC から現在までの秒数を格納しており、4 バイトを占めます (時間精度がミリ秒やナノ秒の場合はさらに多くのバイトが使用されます)。そのため、タイムゾーン付きの時刻と同等になります。セッションのタイムゾーンを設定することで、設定されたタイムゾーンの時刻に自動的に変換されます。
  • Datetime は、「2021-12-05 13:27:53.957033」に似たフォーマットされた文字列を格納しますが、これにはタイムゾーン情報がありません。UTC および CST タイムゾーンで照会された結果は一貫しています。たとえば、「2021-12-05 13:27:53.957033」は CST タイムゾーンで書き込まれますが、UTC タイムゾーンで照会すると、「2021-12-05 13:27:53.957033」のままになります。タイムゾーン変換を行わない場合、CST 時間を UTC 時間に直接マッピングするのと同じですが、実際には UTC 時間は CST 時間より 8 時間遅くなります。

確認する

環境の準備、簡単に言うと、タイムスタンプフィールドと日付時刻フィールドを持つテーブルがあり、現在のサーバーはCSTタイムゾーンにあります

mysql> show テーブル test_time\G を作成します。
************************** 1. 行 ****************************
テーブル: test_time
テーブルの作成: CREATE TABLE `test_time` (
  `id` int NOT NULL AUTO_INCREMENT、
  `ts` タイムスタンプ(6) NULL デフォルト CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  `dt` datetime(6) デフォルト CURRENT_TIMESTAMP(6) 更新時 CURRENT_TIMESTAMP(6)、
  主キー (`id`)
) エンジン=InnoDB AUTO_INCREMENT=3 デフォルト文字セット=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
セット内の 1 行 (0.00 秒)

mysql> '%time_zone%' のような変数を表示します。
+------------------+--------+
| 変数名 | 値 |
+------------------+--------+
| システムタイムゾーン | CST |
| タイムゾーン | システム |
+------------------+--------+
セットに2行(0.01秒)

データを挿入します。ts と dt の結果は、現在の CST タイム ゾーンでは同じになります。

mysql> test_time から * を選択します。
空のセット (0.00 秒)

mysql> test_time() に値を挿入します。
クエリは正常、1 行が影響を受けました (0.00 秒)

mysql> test_time から * を選択します。
+----+----------------------------+----------------------------+
| id | ts | dt |
+----+----------------------------+----------------------------+
| 3 | 2021-12-05 15:04:13.293949 | 2021-12-05 15:04:13.293949 |
+----+----------------------------+----------------------------+
セット内の 1 行 (0.00 秒)

セッションのタイムゾーンを UTC に設定し、再度クエリを実行します。タイムゾーンが CST から UTC に変更されたため、ts クエリの結果は以前よりも 8 時間遅くなります。dt はタイムゾーン情報を保持していないため、結果は変更されません。

mysql> time_zone='+00:00' を設定します。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> test_time から * を選択します。
+----+----------------------------+----------------------------+
| id | ts | dt |
+----+----------------------------+----------------------------+
| 3 | 2021-12-05 07:04:13.293949 | 2021-12-05 15:04:13.293949 |
+----+----------------------------+----------------------------+
セット内の1行(0.01秒)

これは、挿入操作によって生成されたバイナリログにも反映されています。ts は、UTC タイムゾーン情報に相当するタイムスタンプ (1970-01-01 00:00:00 UTC から現在までの秒数) としてバイナリログに保存されます。dt にはタイムゾーン情報がありません。結果は、フォーマットされた文字列 2021-12-05 15:04:13.293949 です。下から 4 行目と 5 行目に注目してください。@2=1638687853.293949 は ts フィールドの値を表し、@3='2021-12-05 15:04:13.293949' は dt フィールドの値を表します。

[mysql %] mysqlbinlog -v --base64-output=デコード行 ./mysqlbin.000012
……
@@SESSION.GTID_NEXT を '1cf4493a-dafd-11eb-944c-4016af29c14c:1416767' に設定します。/*!*/;
# 14220 で
#211205 15:04:13 サーバー ID 1 end_log_pos 14308 CRC32 0x1fd913a3 クエリ thread_id=137 exec_time=0 error_code=0
タイムスタンプを 1638687853.293949/*!*/ に設定します。
始める
//*!*/;
# 14308 で
#211205 15:04:13 サーバー ID 1 end_log_pos 14368 CRC32 0xbb8937fb Table_map: `testa`.`test_time` が番号 121 にマップされました
# 14368 で
#211205 15:04:13 サーバー ID 1 end_log_pos 14423 CRC32 0x2e0a3baa Write_rows: テーブル ID 121 フラグ: STMT_END_F
### `testa`.`test_time` に挿入します
### セット
### @1=3
### @2=1638687853.293949
### @3='2021-12-05 15:04:13.293949'
# 14423 で
#211205 15:04:13 サーバー ID 1 end_log_pos 14454 CRC32 0x68cee280 Xid = 1416
専念 /*!*/;

ピット

  • github.com/go-mysql-org/go-mysqlなどのDTS関連プロジェクトを実行するときにMySQL Binlogを解析するためのオープンソースツールを使用し、タイムスタンプタイプのフィールドは現地時間として解析され、DateTimeタイプはsimeの時間としてin cantas as a sime(time a a sime)as as as as as as as as as as as as as as as as as as a sime( Binlogのネイティブ文字列は、Parsetime = trueを使用しています21-12-05 07:04:13.293949正しい。
  • ビジネスニーズで、time.Now() によって取得されたローカル時間と datetime 型フィールドを比較する必要がある場合は、タイムゾーンの問題に注意するか、時間からタイムゾーンを削除して比較用にフォーマットされた文字列に変換する必要があります。
  • datetime 自体にはタイムゾーン情報がないため、UTC 時間に変換する以外に良い選択肢はなく、これは落とし穴です。

これで、MySQL のタイムスタンプと日付時刻のタイムゾーンの問題によって発生する DTS の落とし穴について詳しく説明しました。MySQL のタイムスタンプと日付時刻の落とし穴の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL における datetime と timestamp の違いと選択
  • MySQL データベースでは、datetime、bigint、timestamp を使用して時間の選択を表します。時間を保存するのに最も効率的なのはどれですか?
  • MySQL における datetime と timestamp の違いと使い方
  • Mysql での日付と時刻の比較
  • MySQL における Datetime と Timestamp の使用の概要

<<:  HTML の 5 種類のスペースの意味

>>:  純粋な CSS を使用してユーザーが Web ページのコンテンツをコピーするのを防ぐ方法

推薦する

Windows (コミュニティ エディション) に MySQL 8.0.18 をインストールするためのチュートリアル

この記事では、Windows で MySQL をインストールする方法について簡単に説明します。他にご...

js+ca​​nvas でコードレイン効果を実現

この記事では、js+ca​​nvasコードの雨効果の具体的なコードを参考までに共有します。具体的な内...

CentOS6.9+Mysql5.7.18 ソースコードのインストール詳細チュートリアル

CentOS6.9+Mysql5.7.18 ソースコードのインストールでは、以下の操作を root ...

MySQL の自動増分主キーが使い果たされた場合の対処方法

面接では、次のようなシナリオを経験する必要があります。インタビュアー: 「MySQL を使用したこと...

bodyタグの主な属性の概要

bgcolor="テキストの色" background="背景画像&q...

Linux のハードリンクとソフトリンクの原理と使用法の分析

Linux システムには、ファイル共有を解決するために使用できるリンク ファイルと呼ばれる種類のファ...

MySQL のジオメトリ型を使用して経度と緯度の距離の問題を処理する方法

テーブルを作成する テーブル `map` を作成します ( `id` int(11) NULLではな...

Linux で Ceph 分散ソフトウェアをインストールして使用する方法に関するチュートリアル

目次序文1. 基本環境1. サービス配信2. ネットワーク構成(全ノード) 3. SSHパスワードフ...

Vueデータ双方向バインディング実装方法

目次1. はじめに2. コードの実装2.1 目的分析2.2 実装プロセス2.2.1 エントリーコード...

nginx でディレクトリ ホワイトリストと IP ホワイトリストを設定する方法

1. ディレクトリホワイトリストを設定する:指定されたリクエストパスに制限を設定しないでください。た...

Vue の this.$router と this.$route の違いと push() メソッド

公式文書には次のように記されている。ルーターを挿入することで、どのコンポーネントでも this.$r...

MySQLアカウントのパスワード変更方法(概要)

序文:データベースを日常的に使用すると、パスワードが単純すぎて変更する必要がある場合、パスワードの有...

div の高さをブラウザの高さに合わせて調整する方法

この古くからある疑問は、数え切れないほどのフロントエンド開発者やバックエンドプログラマーを悩ませてき...

Ubuntu 16.04 に nvidia ドライバー + CUDA + cuDNN をインストールする詳細なチュートリアル

準備1. GPUがCUDAをサポートしているかどうかを確認するlspci | grep -i nvi...

MySqlのインストールとログインの詳細な説明

LinuxにMySQLがすでにインストールされているかどうかを確認する sudo service m...