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 ページのコンテンツをコピーするのを防ぐ方法

推薦する

Vue プロジェクトでブラウザ キャッシュ設定を無効にする例

プロジェクトをリリースするときに、キャッシュをクリーンアップする必要があるという問題に遭遇することが...

MySQL数千万の大規模データに対する30のSQLクエリ最適化テクニックの詳細な説明

1. クエリを最適化するには、テーブル全体のスキャンを避けてください。まず、where と orde...

虫眼鏡コンポーネントのネイティブ js 実装

この記事の例では、参考までに虫眼鏡コンポーネントを開発するためのjsの具体的なコードを共有しています...

ReactアプリケーションにおけるDOM DIFFアルゴリズムの詳細な説明

目次序文VirtualDOM とは何ですか? VirtualDOMを使用する理由DOMレンダリングペ...

Dockerコンテナに入る方法と出る方法

1 Dockerサービスを開始するまず、docker サービスを開始する方法を知っておく必要がありま...

ライフゲームの JavaScript 実装

目次コンセプト紹介論理的ルール完全なコード主な実装コンセプト紹介セルオートマトンとは、コンピュータの...

JavaScriptでカレンダー効果を素早く実装

この記事では、カレンダー効果を素早く実現するためのJavaScriptの具体的なコードを例として紹介...

jQueryはシンプルなボタンの色の変更を実装します

HTML と CSS で、ボタンの色を設定したいとします。 目的の効果は得られますが、プロセスはかな...

CentOS/RHEL システムで VLAN タグ付きイーサネット カードを使用する方法

シナリオによっては、Linux サーバー (CentOS/RHEL) の同じイーサネット カード (...

Tomcatのクラスロードメカニズムのプロセスとソースコード分析

目次序文1. Tomcat クラスローダー構造図: 2. Tomcat のクラスロードプロセスの説明...

Ubuntu システムログで /var/log/messages を設定する方法

1. 問題の説明今日、システム ログ ファイルを確認する必要がありますが、/var/log/mess...

MySQL 外部キー制約の詳細な説明

公式ドキュメント: https://dev.mysql.com/doc/refman/5.7/en/...

Linux での MySQL データベースのアンインストール

Linux で MySQL データベースをアンインストールするにはどうすればいいですか? 以下では、...