亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MySQL?時區(qū)與?serverTimezone詳解

 更新時間:2024年12月20日 09:01:19   作者:AaronLin  
存儲?TIMESTAMP?類型數(shù)據(jù)時,MySQL 會根據(jù)當前會話的時區(qū)將時間轉(zhuǎn)換為 UTC 時間,MySQL 實際存儲的是 UTC 時間,這篇文章主要介紹了MySQL?時區(qū)與?serverTimezone,需要的朋友可以參考下

TL;DR

  • 手動為 MySQL 指定非偏移量的時區(qū),以避免 TIMESTAMP 類型夏令時問題和時區(qū)轉(zhuǎn)化性能瓶頸
  • TIMESTAMP 范圍:'1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07'
  • 連接 MySQL 數(shù)據(jù)庫時,serverTimezone 參數(shù)用于指定數(shù)據(jù)庫服務器的時區(qū),需要設置為與 MySQL 服務端相同的時區(qū)

MySQL 時區(qū)設置影響 TIMESTAMP 類型數(shù)據(jù)和部分時間函數(shù)

MySQL 會話時區(qū)設置會影響 TIMESTAMP 和 時間函數(shù)(NOW()、CURDATE()、CURTIME()、CURRENT_TIMESTAMP())

存儲 TIMESTAMP 類型數(shù)據(jù)時,MySQL 會根據(jù)當前會話的時區(qū)將時間轉(zhuǎn)換為 UTC 時間,MySQL 實際存儲的是 UTC 時間。檢索時 MySQL 根據(jù)會話的時區(qū)將存儲的 UTC 時間轉(zhuǎn)換為會話對應時區(qū)的時間。而 DATETIME 類型的字段存儲的時間值是原始值,不受時區(qū)影響

MySQL 默認使用 SYSTEM 時區(qū)(即操作系統(tǒng)的時區(qū)),每個需要時區(qū)計算的 MySQL 函數(shù)調(diào)用都會調(diào)用系統(tǒng)庫來確定當前系統(tǒng)時區(qū)。此調(diào)用可能受到全局互斥體的保護,從而導致爭用,建議顯式設置時區(qū)

查詢當前時區(qū)

# time_zone:MySQL 使用 SYSTEM 的時區(qū)
# system_time_zone:SYSTEM 為 CST 時區(qū)
show variables like "%time_zone%";
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+

不同會話時區(qū)對 時間函數(shù) 的影響

# 當前時區(qū) 
# 查看當前的全球和會話時區(qū)值
SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;
SELECT NOW(), CURDATE(), CURTIME(), CURRENT_TIMESTAMP();
set time_zone = 'America/New_York';
SELECT NOW(), CURDATE(), CURTIME(), CURRENT_TIMESTAMP();

不同會話時區(qū)對 TIMESTAMP 類型的影響

# UTC +8
set time_zone = 'Asia/Shanghai';
CREATE TABLE events (
    id INT AUTO_INCREMENT PRIMARY KEY,
    event_name VARCHAR(255) NOT NULL,
    event_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    event_datetime DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO events (event_name, event_timestamp, event_datetime) VALUES ('10.24 15:45:00', '2022-10-24 15:45:00', '2022-10-24 15:45:00');
INSERT INTO events (event_name, event_timestamp, event_datetime) VALUES ('12.24 15:45:00', '2022-12-24 15:45:00', '2022-12-24 15:45:00');
SELECT * FROM events;
+----+----------------+---------------------+---------------------+
| id | event_name     | event_timestamp     | event_datetime      |
+----+----------------+---------------------+---------------------+
|  1 | 10.24 15:45:00 | 2022-10-24 15:45:00 | 2022-10-24 15:45:00 |
|  2 | 12.24 15:45:00 | 2022-12-24 15:45:00 | 2022-12-24 15:45:00 |
+----+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)
# 僅修改當前會話的時區(qū)
set time_zone = 'America/New_York';
SELECT * FROM events;
+----+----------------+---------------------+---------------------+
| id | event_name     | event_timestamp     | event_datetime      |
+----+----------------+---------------------+---------------------+
|  1 | 10.24 15:45:00 | 2022-10-24 03:45:00 | 2022-10-24 15:45:00 |    <- 夏令時,相差 12 小時
|  2 | 12.24 15:45:00 | 2022-12-24 02:45:00 | 2022-12-24 15:45:00 |    <- 平時相差 13 小時
+----+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)

紐約 UTC 時差通常為 UTC-5(EST),夏令時為 UTC-4(EDT),所以將原本的會話從上海(UTC+8) 轉(zhuǎn)到紐約時,TIMESTAMP 相差了 13 或 12(夏令時) 小時,所以為了自動轉(zhuǎn)換夏令時,指定時區(qū)最好使用時區(qū)名詞 Asia/Shanghai,避免使用偏移量:'+08:00'

JDBC 連接 MySQL 時 serverTimezone 對于 TIMESTAMP 類型的影響

連接 MySQL 時我們使用 URL:jdbc:mysql://192.168.1.2:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai

這里的 serverTimezone 參數(shù)用于指定連接到 MySQL 數(shù)據(jù)庫時所使用的時區(qū),不顯示指定使用 JVM 默認時區(qū)

MySQL 服務端處理 TIMESTAMP :寫入時根據(jù)會話時區(qū)轉(zhuǎn)為 UTC 時間戳存儲,讀取時將 UTC 還原為會話時區(qū)的時間,保證了寫入和讀取數(shù)據(jù)的一致。數(shù)據(jù)庫會話時區(qū)與 JVM 時區(qū)相同時,JVM 讀寫的 TIMESTAMP 一致,如果不一致就會出現(xiàn)問題,serverTimezone 就是為了告訴 JDBC 從 MySQL 服務端獲取到的 TIMESTAMP 是什么時區(qū),知道了它所使用的時區(qū),JDBC 就可以進行預處理

MyBatis 在處理 TIMESTAMP 類型的數(shù)據(jù)時會有一些差異,實體映射為 Timestamp 或 Date 在讀寫時會進行上面提到的預處理,而 LocalDateTime 則不會

JDBC 讀取 TIMESTAMP 類型數(shù)據(jù)時

JDBC 執(zhí)行命令時,調(diào)用不同的 ResultSet 方法會有不同結(jié)果:

  • ResultSet 的 getString 方法:直接讀取時間,即直接返回 數(shù)據(jù)庫根據(jù)會話時區(qū)轉(zhuǎn)化后的時間
  • ResultSet 的 getTimestamp 方法:將 數(shù)據(jù)庫根據(jù)會話時區(qū)轉(zhuǎn)化后的時間 根據(jù) serverTimezone 設置的時區(qū)進行轉(zhuǎn)化,得到 數(shù)據(jù)庫根據(jù)會話時區(qū)轉(zhuǎn)化后的時間 對應的 UTC 時間毫秒戳,然后將這個 UTC 毫秒時間戳轉(zhuǎn)換為 Timestamp 類型(它本身不包含時區(qū)信息),打印時會根據(jù) JVM 的時區(qū)轉(zhuǎn)化為對應的時區(qū)時間

getTimestamp 轉(zhuǎn)化 Timestamp 的源碼在:com.mysql.cj.result.SqlTimestampValueFactory

這里的 this.connectionTimeZone 就是連接 url 中指定的 serverTimezone

假設 MySQL 默認設置的會話時區(qū)為 Asia/Shanghai,通過默認會話讀取該 TIMESTAMP 的值為:2022-10-24 15:45:00。而 MySQL 實際存儲的 TIMESTAMP 為 UTC 時間:2022-10-24 07:45:00。MySQL JDBC 驅(qū)動通過默認會話獲取該值時,MySQL 會自動根據(jù)默認時區(qū)提供轉(zhuǎn)化好時間:2022-10-24 15:45:00,驅(qū)動則會根據(jù) serverTimezone 配置的時區(qū),將 MySQL 的時間轉(zhuǎn)化為 Calendar 對象,通過 c.getTimeInMillis() 獲取對應的 UTC 時間戳,用于創(chuàng)建 Timestamp 對象

JDBC 寫入 TIMESTAMP 類型:

  • now()寫入,數(shù)據(jù)庫 server 端會獲取數(shù)據(jù)庫當前時區(qū)
  • 按照字符串寫入:MySQL 服務端根據(jù)會話時區(qū)轉(zhuǎn)成對應的 UTC 毫秒數(shù)存儲
  • 通過變量綁定寫入:傳入 Timestamp 對象,JDBC 將其編碼為 serverTimezone 所代表的時間字符串,類似:2022-06-22 03:29:29,然后發(fā)送給 MySQL 服務端

驗證

import org.junit.jupiter.api.Test;
import java.sql.*;
import java.util.TimeZone;
public class JDBCTest {
    private static String url = "jdbc:mysql://host:3306/mydb?useSSL=false&serverTimezone=UTC";
    private static String username = "root";
    private static String password = "";
    @Test
    void testInsertTimestamp() {
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        try (Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement ps = connection
                .prepareStatement("insert into events(id,event_name,event_timestamp,event_datetime) values (1,'now()',now(),now())");) {
            ps.execute();
        }catch (Exception e){
            e.printStackTrace();
        }
        try (Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement ps = connection
                .prepareStatement("insert into events(id,event_name,event_timestamp,event_datetime) values (2,'2022-06-22 03:29:29','2022-06-22 03:29:29', '2022-06-22 03:29:29')");) {
            ps.execute();
        }catch (Exception e){
            e.printStackTrace();
        }
        try (Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement ps = connection
                .prepareStatement("insert into events(id,event_name,event_timestamp,event_datetime) values (3,'1733539800000L',?,?)")) {
            // Sat Dec 07 2024 02:50:00 GMT+0000
            // Sat Dec 07 2024 10:50:00 GMT+0800 (中國標準時間)
            long timestamp = 1733539800000L;
            Timestamp ts1 = new Timestamp(timestamp);
            Timestamp ts2 = new Timestamp(timestamp);
            ps.setTimestamp(1, ts1);
            ps.setTimestamp(2, ts2);
            ps.execute();
            // 根據(jù) serverTimezone 將 Timestamp 預處理為 UTC 時間:2024-12-07 02:50:00
            // 相當于執(zhí)行下列 SQL
            // insert into events(id,event_name,event_timestamp,event_datetime) values (3,'1733539800000L','2024-12-07 02:50:00','2024-12-07 02:50:00')
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @Test
    void testGetTimestamp() {
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        try (Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement ps = connection
                .prepareStatement("select * from events where id=3"); ResultSet rs = ps.executeQuery();) {
            while (rs.next()) {
                // getTimestamp is 2024-12-07 10:50:00.0
                // 根據(jù) serverTimezone,認定數(shù)據(jù)庫時區(qū)為 UTC,轉(zhuǎn)化為 本地 Asia/Shanghai 需要 +8,則預處理為:2024-12-07 10:50:00.0
                System.out.println("getTimestamp is " + rs.getTimestamp("event_timestamp"));
                // getString is 2024-12-07 02:50:00
                System.out.println("getString is " + rs.getString("event_datetime"));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

實驗環(huán)境:
MySQL 8.0.40
mysql-connector-j 9.1.0
mybatis-spring-boot-starter 3.0.4

參考資料

7.1.15 MySQL Server Time Zone Support

13.2.2 The DATE, DATETIME, and TIMESTAMP Types

一文講透MySQL driver讀取時間時的時區(qū)處理

修改mysql時區(qū)的三種方法

MySQL 中存儲時間的最佳實踐

到此這篇關于MySQL 時區(qū)與 serverTimezone的文章就介紹到這了,更多相關mysql  serverTimezone內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MySQL數(shù)據(jù)庫定時任務舉例講解

    MySQL數(shù)據(jù)庫定時任務舉例講解

    最近項目里面的后臺需要用到定時任務,而MySQL從5.0開始自帶了定時事件操作,所以學習下并做下記錄,下面這篇文章主要給大家介紹了關于MySQL數(shù)據(jù)庫定時任務的相關資料,需要的朋友可以參考下
    2023-06-06
  • MySQL InnoDB 事務鎖源碼分析

    MySQL InnoDB 事務鎖源碼分析

    InnoDB 事務鎖,事務鎖實現(xiàn)起來的代碼卻是又臭又硬的好大一坨,各種細節(jié),今天小編在這里整理一個源碼閱讀筆記,把那一坨加鎖相關的代碼提煉出來,感興趣的小伙伴別忘記收藏奧
    2021-09-09
  • MySQL?InnoDB鎖類型及鎖原理實例解析

    MySQL?InnoDB鎖類型及鎖原理實例解析

    這篇文章主要為大家介紹了MySQL?InnoDB鎖類型及鎖原理實例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • ubuntu20.04配置mysql8.0的實現(xiàn)步驟

    ubuntu20.04配置mysql8.0的實現(xiàn)步驟

    本文主要介紹了ubuntu20.04配置mysql8.0的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • MySQL-MMM安裝指南(Multi-Master Replication Manager for MySQL)

    MySQL-MMM安裝指南(Multi-Master Replication Manager for MySQL)

    這篇文章主要介紹了mysql Multi-Master Replication Manager for MySQL的安裝方法,需要的朋友可以參考下
    2014-02-02
  • mysqldump參數(shù)詳細說明及用途

    mysqldump參數(shù)詳細說明及用途

    ??mysqldump?? 是一個強大的工具,用于從 MySQL 數(shù)據(jù)庫中導出數(shù)據(jù),它支持多種輸出格式,包括 ??CSV??、??SQL??、??XML?? 等,在本文中,我們將詳細介紹 ??mysqldump?? 的一些常用參數(shù),以及它們的用途,感興趣的朋友一起看看吧
    2024-12-12
  • mysql如何創(chuàng)建和刪除唯一索引(unique key)

    mysql如何創(chuàng)建和刪除唯一索引(unique key)

    這篇文章主要介紹了mysql如何創(chuàng)建和刪除唯一索引(unique key)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Debian 6.02 (squeeze)下編譯安裝 MySQL 5.5的方法

    Debian 6.02 (squeeze)下編譯安裝 MySQL 5.5的方法

    Debian 6.02 (squeeze)下編譯安裝 MySQL 5.5的方法,需要的朋友可以參考下。
    2011-12-12
  • MySQL字段為 NULL的5大坑

    MySQL字段為 NULL的5大坑

    本文主要介紹了MySQL字段為 NULL的5大坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • Mysql導入導出時遇到的問題解決

    Mysql導入導出時遇到的問題解決

    這篇文章主要給大家介紹了關于Mysql導入導出時遇到問題的解決方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Mysql具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08

最新評論