mysqlはタイムゾーン関連の問題を解決します

mysqlはタイムゾーン関連の問題を解決します

序文:

MySQL を使用すると、時間の表示が正しくない、タイムゾーンが GMT+8 ゾーンにない、プログラムによって取得された時間とデータベースに保存された時間が一致しないなど、タイムゾーン関連の問題が発生することがあります。実は、これらの問題はすべてデータベースのタイムゾーン設定に関連しています。この記事では、データベースのパラメータから始めて、徐々にタイムゾーンに関連する内容を紹介します。

1. log_timestampsパラメータの紹介

まず、 log_timestampsパラメータはタイムゾーンには影響しませんが、設定が異なると一部のログ レコードの時間に影響します。このパラメータは主にエラー ログ、スロー ログ、ジェネラル ログ ログ ファイルの表示時間を制御しますが、テーブルに書き込まれるジェネラル ログとスロー ログ (mysql.general_log、mysql.slow_log) の表示時間には影響しません。

log_timestamps は動的に変更できるグローバル パラメータです。デフォルトでは UTC タイム ゾーンが使用されるため、ログに記録される時間は北京時間より 8 時間遅くなり、ログの表示が不便になります。システムのタイムゾーンを使用するには、SYSTEM に変更することができます。以下は、このパラメータの機能と変更方法の簡単なテストです。

# パラメータ値を表示する ​​mysql> show global variables like 'log_timestamps';
+----------------+-------+
| 変数名 | 値 |
+----------------+-------+
| ログタイムスタンプ | UTC |
+----------------+-------+
セット内の 1 行 (0.00 秒)

# スローログを生成するmysql> select sleep(10),now();
+-----------+---------------------+
| スリープ(10) | 今() |
+-----------+---------------------+
| 0 | 2020-06-24 17:12:40 |
+-----------+---------------------+
セット内の1列(10.00秒)

# スローログファイルには、検出時刻が UTC 時間で記録されます。# 時刻: 2020-06-24T09:12:50.555348Z
# ユーザー@ホスト: root[root] @ localhost [] Id: 10
# クエリ時間: 10.000354 ロック時間: 0.000000 送信行数: 1 検査行数: 1
タイムスタンプを1592989960に設定します。
sleep(10),now()を選択します。

# パラメータ値を変更して再度テストします。mysql> set global log_timestamps = SYSTEM;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> sleep(10),now() を選択します。
+-----------+---------------------+
| スリープ(10) | 今() |
+-----------+---------------------+
| 0 | 2020-06-24 17:13:44 |
+-----------+---------------------+
セット内の1列(10.00秒)

# スローログファイルの記録内容の時間は正しいです# 時間: 2020-06-24T17:13:54.514413+08:00
# ユーザー@ホスト: root[root] @ localhost [] Id: 10
# クエリ時間: 10.000214 ロック時間: 0.000000 送信行数: 1 検査行数: 1
タイムスタンプを1592990024に設定します。
sleep(10),now()を選択します。

2. time_zoneパラメータの紹介

time_zoneパラメータは、各接続セッションのタイムゾーンを設定するために使用されます。このパラメータはグローバル レベルとセッション レベルに分かれており、動的に変更できます。デフォルト値は SYSTEM です。この場合、グローバル パラメータ system_time_zone の値が使用されます。system_time_zone は、デフォルトで現在のシステムのタイム ゾーンから継承されます。つまり、MySQL のタイム ゾーンは、デフォルトではシステムのタイム ゾーンと同じです。

タイムゾーン設定は主に、タイムゾーンに左右される時間値の表示と保存に影響します。これには、一部の関数(now() や curtime() など)によって表示される値や、TIMESTAMP 型に格納される値が含まれます。ただし、これらのデータ型はアクセス時にタイムゾーンに変換されないため、DATE、TIME、DATETIME 列の値には影響しません。TIMESTAMP 型は実際には UTC 時間をデータベースに格納しており、クエリを実行すると特定のタイムゾーンに応じて異なる時間が表示されます。

次に、time_zone パラメータを変更した場合の影響をテストします。

# Linuxシステムの時間とタイムゾーンを確認する [root@centos ~]# date
2020年6月28日日曜日 14:29:10 CST

# MySQL の現在のタイムゾーンと時刻を表示します。mysql> show global variables like '%time_zone%';
+------------------+--------+
| 変数名 | 値 |
+------------------+--------+
| システムタイムゾーン | CST |
| タイムゾーン | システム |
+------------------+--------+
セット内の 2 行 (0.00 秒)

mysql> now() を選択します。
+---------------------+
| 今() |
+---------------------+
| 2020-06-28 14:31:12 |
+---------------------+
セット内の 1 行 (0.00 秒)

# テストテーブルを作成し、データを挿入します。mysql> CREATE TABLE `time_zone_test` (
  -> `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自動増分主キー',
  -> `dt_col` datetime デフォルト NULL コメント 'datetime time',
  -> `ts_col` タイムスタンプ デフォルト NULL コメント 'timestamp time',
  -> 主キー (`id`)
  -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='time_zone テストテーブル';
クエリは正常、影響を受けた行は 0 行、警告は 1 件 (0.07 秒)

mysql> time_zone_test (dt_col,ts_col) に値 ('2020-06-01 17:30:00','2020-06-01 17:30:00'),(now(),now()); を挿入します。
クエリは正常、2 行が影響を受けました (0.01 秒)
記録: 2 重複: 0 警告: 0

mysql> time_zone_test から * を選択します。
+----+---------------------+---------------------+
| id | dt_col | ts_col |
+----+---------------------+---------------------+
| 1 | 2020-06-01 17:30:00 | 2020-06-01 17:30:00 |
| 2 | 2020-06-28 14:34:55 | 2020-06-28 14:34:55 |
+----+---------------------+---------------------+

# UTC タイムゾーンに変更して再接続します。タイムスタンプに保存されている時間はタイムゾーンによって変わることがわかります。mysql> set global time_zone='+0:00';
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
mysql> time_zone='+0:00' を設定します。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

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

mysql> now() を選択します。
+---------------------+
| 今() |
+---------------------+
| 2020-06-28 06:36:16 |
+---------------------+
セット内の 1 行 (0.00 秒)

mysql> time_zone_test から * を選択します。
+----+---------------------+---------------------+
| id | dt_col | ts_col |
+----+---------------------+---------------------+
| 1 | 2020-06-01 17:30:00 | 2020-06-01 09:30:00 |
| 2 | 2020-06-28 14:34:55 | 2020-06-28 06:34:55 |
+----+---------------------+---------------------+
セット内の 2 行 (0.00 秒)

# 東部 8 タイム ゾーンに戻して通常の状態に戻します。mysql> set global time_zone='+8:00';
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

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

mysql> '%time_zone%' のようなグローバル変数を表示します。
+------------------+--------+
| 変数名 | 値 |
+------------------+--------+
| システムタイムゾーン | CST |
| タイムゾーン | +08:00 |
+------------------+--------+
セット内の 2 行 (0.00 秒)

mysql> now() を選択します。
+---------------------+
| 今() |
+---------------------+
| 2020-06-28 14:39:14 |
+---------------------+
セット内の 1 行 (0.00 秒)

mysql> time_zone_test から * を選択します。
+----+---------------------+---------------------+
| id | dt_col | ts_col |
+----+---------------------+---------------------+
| 1 | 2020-06-01 17:30:00 | 2020-06-01 17:30:00 |
| 2 | 2020-06-28 14:34:55 | 2020-06-28 14:34:55 |
+----+---------------------+---------------------+
セット内の 2 行 (0.00 秒)

永続的にしたい場合は、設定ファイルに書き込む必要があります。たとえば、タイムゾーンを East 8 に変更する場合は、構成ファイルの [mysqld] セクションに default_time_zone = '+8:00' という行を追加する必要があります。

3. よくあるタイムゾーンの問題とその回避方法

タイムゾーンの設定が不適切だと、さまざまな問題が発生する可能性があります。一般的な問題と解決策を以下に示します。

3.1 MySQLの内部時間は北京時間ではない

このような問題が発生した場合は、まずシステム時間とタイムゾーンが正しいかどうかを確認し、次に MySQL の time_zone を確認します。time_zone を '+8:00' に変更することをお勧めします。

3.2 Javaプログラムがアクセスした時刻はデータベースの時刻と8時間異なる

この問題は、プログラムのタイム ゾーンとデータベースのタイム ゾーンの不一致によって発生する可能性が最も高くなります。両側のタイムゾーンを確認できます。北京時間を一律に使用したい場合は、jdbc 接続文字列に serverTimezone=Asia/Shanghai を追加し、MySQL の time_zone を '+8:00' に変更することもできます。

3.3 プログラム時間はデータベース時間と13時間または14時間異なります

8 時間の差がそれほど驚くべきことではないとしても、13 時間の差となると多くの人が首をかしげるかもしれません。この問題は、JDBC と MySQL が「CST」タイムゾーンのネゴシエーションに同意しないために発生します。 CST タイムゾーンは非常に紛らわしいタイムゾーンであるため、次の 4 つの意味があります。

  • 中央標準時(米国) UTC-05:00 または UTC-06:00
  • 中央標準時(オーストラリア) UTC+09:30
  • 中国標準時 UTC+08:00
  • キューバ標準時 UTC-04:00

MySQL では、time_zone がデフォルトの SYSTEM 値である場合、タイムゾーンはシステム タイムゾーン CST として継承され、MySQL では内部的に UTC+08:00 と見なされます。 JDBC では、CST を米国中部標準時とみなすため、13 時間の差が生じます。冬時間の場合は、14 時間の差が生じます。

この問題の解決方法も非常に簡単です。MySQL データベースのタイム ゾーンを明示的に指定できます。誤解を招く CST を使用する代わりに、time_zone を '+8:00' に変更し、jdbc 接続文字列に serverTimezone=Asia/Shanghai を追加します。

3.4 タイムゾーンの問題を回避する方法

上記のタイムゾーンの問題を回避する方法について、いくつかアイデアがあるかもしれません。以下に簡単にまとめます。

  1. まず、システムのタイムゾーンが正確であることを確認します。
  2. タイム ゾーンは、jdbc 接続文字列で指定され、データベースのタイム ゾーンと一致します。
  3. 誤解を招きやすい CST の使用を避けるため、time_zone パラメータの推奨設定は '+8:00' です。
  4. 各環境のデータベース インスタンスのタイム ゾーン パラメータは同じままです。

データベースの time_zone パラメータはデフォルトの SYSTEM 値を選択し、プログラム時間とデータベース時間の間に矛盾はないと言う学生もいるかもしれません。この時点でtime_zoneを「+8:00」に変更する必要がありますか?この場合、特に TIMESTAMP フィールドが頻繁に照会される場合は、time_zone を '+8:00' に変更することをお勧めします。time_zone=system の場合、timestamp フィールドを照会すると、タイムゾーン変換のためにシステム タイムゾーンが呼び出されますが、これはグローバル ロック __libc_lock_lock によって保護されており、スレッド同時実行環境ではシステム パフォーマンスが制限される可能性があるためです。これを '+8:00' に変更すると、システムのタイムゾーン変換はトリガーされず、MySQL 独自の変換が使用されるため、パフォーマンスが大幅に向上します。

要約:

この記事を読んだ後、データベースのタイムゾーンについてより深く理解できましたか?この記事が、特に MySQL のタイムゾーンについて詳しく知りたい方にとって役立つことを願っています。その他のタイムゾーン関連の問題が発生した場合は、メッセージを残してご相談ください。

上記は、MySQL がタイムゾーン関連の問題を解決する方法の詳細です。MySQL のタイムゾーン関連の問題の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Java における MySQL タイムゾーン問題の詳細な説明
  • MySQL でタイムゾーンを表示および変更する方法
  • MySQL タイムゾーンを変更する方法の概要
  • MySQL クエリ時に文字列の大文字と小文字を区別する方法
  • mysql タイムゾーンの問題
  • MySQL 8.0 のタイムゾーン問題を解決する手順

<<:  Ubuntu 16.04 カーネルのアップグレード手順

>>:  Vue.js スロットにおけるスコープ付きスロットの使用法の詳細な説明

推薦する

ラベルタグを使用してテキストをクリックしてラジオボタンを選択します

<label> タグは、入力要素のラベル (タグ) を定義します。ラベル要素はユーザーに...

1 行のコードでさまざまな IE 互換性の問題を解決します (IE6-IE10)

x-ua-compatible は、IE ブラウザがページを解析およびコンパイルするためのモデルを...

MySQL 8.0.18 ハッシュ結合は左/右結合をサポートしていません 左と右の結合の問題

MySQL 8.0.18 では、インデックスが作成されていないフィールドに適用でき、等価値の関連付け...

MySQL インデックスが失敗するいくつかの状況の概要

1. インデックスはnull値を保存しないより正確に言うと、単一列インデックスには null 値は格...

Bツリー挿入プロセスの概要

前回の記事 https://www.jb51.net/article/154153.htm では、B...

角度でechartsマップを使用する詳細な説明

目次echartの初期化アプリベースチャートコンポーネントhtml CS app-base-char...

MySQLのクラスタモードでのgalera-clusterのデプロイメントの詳細説明

目次1: galera-clusterの紹介2. galera-clusterの仕組み3: Mari...

CSS3 シンプルカットカルーセル画像実装コード

実装のアイデアまず、親コンテナーを作成し、2 つの順序なしリストを使用して、柔軟なレイアウトで親コン...

Docker 経由で wsl の tar ファイルを作成する方法

最近VScodeのリモート開発機能をいじっています。Dockerのコンテナに接続できるほか、WSLに...

Dockerリンクはコンテナの相互接続を実現します

目次1.1. IP経由のコンテナ間のネットワークアクセス1.2. コンテナ名またはコンテナIDによる...

HTML_PowerNode Java アカデミーでテーブルを動的に追加する

さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <html> <...

Nginx リバース プロキシはポート 80 のリクエストを 8080 に転送します

まず、一連の概念を理解しましょう。nginx リバース プロキシとは何でしょうか?リバース プロキシ...

Vuexはセッションストレージデータを結合して、ページを更新するときにデータが失われる問題を解決します

目次序文1. 理由: 2. 解決策のアイデア: 1. ローカル保存方法: 2. 実装手順: 3. 最...

レスポンシブ原則と Vue2.0/3.0 の違いについての簡単な分析

序文vue3.0 が正式にリリースされて以来、多くの友人が vue3.0 に切り替えました。ここでは...