存在資料庫的utc時間_資料庫時間不是utc時間 - CSDN

2020-11-18 CSDN技術社區

作者:Gods_巨蟻

引言

近期團隊的個別項目在進行框架升級後,部分時間值存在8小時誤差,原因是錯誤的將資料庫中的時間數據理解成了UTC時間(舊版本認為是北京時間)

考慮到未來項目對於時間理解的一致性,我決定將項目統一為使用UTC時間,經調研,形成本文

 

mysql資料庫時區及時間時間類型說明

資料庫時區

mysql資料庫擁有時區設置,默認使用系統時區

可通過如下語句查詢當前時區

show variables like '%time_zone%';

 

下圖為我個人機器上mysql資料庫時區設置:

 

 

項目線上資料庫時區設置如下:

 

可見資料庫使用系統時間CST——China Standard Time UTC+8:00 中國沿海時間(北京時間)

 

時間類型說明

datetime

實際格式儲存(Just stores what you have stored and retrieves the same thing which you have stored.)

與時區無關(It has nothing to deal with the TIMEZONE and Conversion.)

 

timestamp

值以UTC毫秒數保存( it stores the number of milliseconds)

存儲及檢索時根據當前時區設置,對時間數值做轉換

 

由於timestamp與時區相關,且線上資料庫時區設置為北京時間(即UTC+8:00)。因此,當資料庫中使用了timestamp列,若使用不當,統一UTC格式時間改造將很可能會引入錯誤! 後面詳述理由

 

統一UTC時間改造方案簡述

統一時區設定

項目新框架中通過UTCTimeZoneConfiguration類型,在項目初始化時設置當前進程的默認時區

@Configurationpublic class UTCTimeZoneConfiguration implements ServletContextListener{ public void contextInitialized(ServletContextEvent event) { System.setProperty("user.timezone", "UTC"); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); } public void contextDestroyed(ServletContextEvent event) {}}

  

時間類型Joda DateTime的使用方式

日期時間類型可以使用 java.util.Date,但推薦使用更為方便的joda DateTime,本節介紹joda DateTime 序列化/反序列化使用方式

 

Joda DateTime 類型用於定義接口輸入輸出參數,需進行序列化/反序列化操作。與原生的Date類型不同,DateTime需要做一點額外處理

 

1、Model類型的日期欄位使用類型DateTime替代Date

實例代碼如下

public class Entity { @JsonSerialize(using = UTCDateTimeSerializer.class) @JsonDeserialize(using = UTCDateTimeDeserializer.class) private DateTime dateTime; public DateTime getDateTime() { return dateTime; } public void setDateTime(DateTime dateTime) { this.dateTime = dateTime; }}

  其中UTCDateTimeSerializer與UTCDateTimeDeserializer類的實現見附錄

 

2、Get請求接受時間參數

此時,一種有效的處理方式是使用字符串接受日期參數,如下:

@RequestMapping(value = "/xxx", method = RequestMethod.GET) public CommonResponse getXxx(@RequestParam(value = "beginTime") String beginTimeText, @RequestParam(value = "endTime") String endTimeText) { DateTime beginTime = DateTime.parse(beginTimeText).withZone(DateTimeZone.UTC); DateTime endTime = DateTime.parse(endTimeText).withZone(DateTimeZone.UTC); ... }

  

Dao時間操作——針對資料庫列為datetime的場景

以Joda DateTime類型舉例說明使用方法,某Dao類型中存在的兩個方法如下:

public void update(int id, DateTime dateTime) { String sql = "UPDATE " + TABLE_NAME + " SET datetime = ? WHERE id = ?"; jdbcTemplate.update(sql, new Timestamp(dateTime.getMillis()), id); } public DateTime getDateTime(int id) { String sql = "SELECT datetime FROM " + TABLE_NAME + " WHERE id = ?"; List<DateTime> dateTimeList = jdbcTemplate.query(sql, new Object[] {id}, new RowMapper<DateTime>() { @Override public DateTime mapRow(ResultSet rs, int rowNum) throws SQLException { return new DateTime(rs.getTimestamp("datetime").getTime()); } }); return dateTimeList.size() > 0 ? dateTimeList.get(0) : null; }

 插入或更新數據,傳遞的時間參數請使用 new Timestamp(dateTime.getMillis())

讀取時間參數,使用new DateTime(rs.getTimestamp("datetime").getTime())

 

Dao時間操作——針對資料庫列為timestamp的場景

資料庫timestamp類型適合用來記錄數據的最後修改時間

其他場景建議使用datetime或者int

 

方案一 更改會話時區為UTC時間

對timestamp列的操作與datetime列的操作不做區分,此時需要設置數據連接會話的時區,默認為北京時間,需要設置為UTC時間,通過如下語句設置

set time_zone = '+0:00';

 

實際項目中使用資料庫連接池,創建datasource後使用如下方式設置時區,將對所有連接生效

dataSource.setInitSQL("set time_zone = '+0:00'");

 

經此操作後,時區統一為UTC時間,Dao中時間操作,無需對timestamp做特殊處理

 

方案二 不更改會話時區

由於不更改時區,timestamp類型數據的使用存在一定限制

1、 如何更新timestamp數據

對於資料庫表中的timestamp列,其值的更新應當由資料庫自行維護,在create table時設置,如下:

CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);

 可簡寫如下

CREATE TABLE t1 ( ts TIMESTAMP);

  不允許程序自主更新timstamp列數據

線上資料庫時區為北京時間,其接受到的日期數據被視為北京時間,而上層程序業務邏輯統一使用UTC時間,時區不統一。因此避免資料庫記錄的日期數據理解不一致,不允許程序通過寫操作sql語句更新timestamp列

 

下圖數據為本人實測數據,timestamp列由程序進行更新,update_time列則由資料庫自動更新

 

前者顯示的是UTC時間,看似合理,實則錯誤,資料庫內部存儲時間為UTC-8:00

update_time符合資料庫時區設置,返回北京時間,內部實際存儲UTC時間

 

2、 如何讀取timestamp數據

為避免從資料庫中獲取時區相關時間(北京時間),強制使用UTC時間,使用函數UNIX_TIMESTAMP獲取1970年至今秒數,轉換成DateTime時乘以1000轉變為毫秒

public DateTime getTimestamp(int id) { String sql = "SELECT UNIX_TIMESTAMP(update_time) as unix_timestamp FROM " + TABLE_NAME + " WHERE id = ?"; List<DateTime> dateTimeList = jdbcTemplate.query(sql, new Object[] {id}, new RowMapper<DateTime>() { @Override public DateTime mapRow(ResultSet rs, int rowNum) throws SQLException { return new DateTime(rs.getLong("unix_timestamp") * 1000); } }); return dateTimeList.size() > 0 ? dateTimeList.get(0) : null; }

 

附錄

Mysql時區設置

設置全局時區,需要管理員權限

使用本機系統時區

SET GLOBAL time_zone = SYSTEM;

使用UTC時間

SET GLOBAL time_zone = '+0:00';

使用北京時間

SET GLOBAL time_zone = '+8:00';

設置當前連接會話時區

 

UTCDateTimeSerializer與UTCDateTimeDeserializer

UTCDateTimeSerializer 完成DateTime對象到UTC時間字符串的轉換,格式為:yyyy-MM-ddTHH:mm:ssZ

UTCDateTimeDeserializer 完成時間字符串到DateTime對象的轉換,轉換為UTC時區

 

具體實現如下:

public class UTCDateTimeSerializer extends JsonSerializer<DateTime> { @Override public void serialize(DateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException { String dateTimeAsString = dateTime.withZone(DateTimeZone.UTC).toString(BecConstant.DATETIME_FORMAT); jsonGenerator.writeString(dateTimeAsString); }}public class UTCDateTimeDeserializer extends JsonDeserializer<DateTime> { @Override public DateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { JsonToken currentToken = jsonParser.getCurrentToken(); if (currentToken == JsonToken.VALUE_STRING) { String dateTimeAsString = jsonParser.getText().trim(); return DateTime.parse(dateTimeAsString).withZone(DateTimeZone.UTC); } return null; }}

相關焦點

  • InfluxDB - 開源的時間序列資料庫簡介及安裝
    InfluxDB什麼是時間序列資料庫,最簡單的定義就是數據格式裡包含Timestamp欄位的數據,比如某一時間磁碟使用率、網絡流量、CPU的使用率等。InfluxDB是一個開源的時間序列資料庫,一個開源的沒有外部依賴的時間序列資料庫。適用於記錄度量,事件及執行分析。
  • InfluxData為時間序列資料庫軟體籌集了6000萬美元
    今天產生的數據量令人難以置信 - 僅美國公司每天就產生2.5個五分之一字節,足以在一年內填補一萬個國會圖書館 - 其中大部分是時間序列的變化(即數據點及時索引)訂購)。根據Forrester Research的數據,鑑於數量龐大,難怪只有12%的公司表示他們正在分析他們擁有的數據。
  • 關於GPS時間與UTC/GMT時間,你需要知道的都在這裡
    這是因為以前在天文觀測中,常常把每天的起始(0時)定為正午,而不是通常民用的午夜,給格林威治平時的意義造成含糊,人們使用世界時(Universal Time, UT)一詞來明確表示每天從午夜開始的格林威治平時。UT(世界時)也有幾種表示,UTO表示未經改正的世界時,UT1表示經過極移改正的世界時,UT2表示進一步經過地球自轉速度的季節性改正後的世界時。
  • MySQL資料庫教程-資料庫創建與刪除操作
    資料庫創建與刪除顧名思義,資料庫是指數據存儲的倉庫,資料庫使用者可以通過資料庫對象實現數據存儲、管理與維護。因此資料庫的創建操作是資料庫使用的第一步與基礎。在MySQL資料庫管理系統中,資料庫的創建與資料庫刪除操作較為簡單,本文主要介紹資料庫創建與資料庫刪除操作,本文配套視頻課程請點擊資料庫創建與刪除。
  • 圖資料庫的類別有哪些?數易軒解讀:圖資料庫分類與原理
    圖資料庫作為新興NoSQL資料庫的代表,可以分為四種類型。圖資料庫應用廣泛,無論是網際網路行業還是傳統的金融、地產、醫療等行業,都可以通過圖資料庫的應用進一步提升企業效率。數易軒致力於圖資料庫技術服務,為您介紹圖資料庫的四個分類。
  • 作為資料庫核心成員,如何讓淘寶不卡頓?
    時間倒轉穿越回2007年年底一覺醒來,我還是照常去上班,走到西溪溼地附近,馬路沒有,高樓沒有,有的是小山坡和金色的稻田。一番打聽之後,才知道此時沒有什麼西溪園區。沒辦法,硬著頭皮去濱江上班,一刷卡,才發現我並不是我,我現在的身份是淘寶資料庫團隊的核心成員。此時全國上下在迎接著奧運的到來,一片祥和。
  • Intouch的SQL資料庫訪問
    建立ODBC數據源運行數據源,找到數據源(ODBC)點添加拉到底選擇SQL SERVER寫個名字,伺服器如果本地選本地,如果不是本地,在下拉裡面找一個.配置登陸權限,用win帳戶或者用戶名密碼方式都可以。自己選。在下來裡面找到你要連接的資料庫。然後測試連接,成功後。
  • 非關係型資料庫NoSQL的崛起
    文章主要介紹了最古老的NoSQL資料庫之一CouchDB,這種資料庫的創造者達米安·卡茨受到了在線協作平臺Lotus Notes的啟發,他的故事有助於幫助解釋NoSQL運動的興起,及為何這種資料庫與以往的資料庫存在如此巨大的差異。以下是這篇文章的全文:在追溯NoSQL運動的源頭時,大多數網際網路人士都會想到谷歌(微博)和亞馬遜。
  • 圖資料庫的作用有哪些?圖資料庫怎麼樣?
    圖資料庫怎麼樣你知道圖資料庫是什麼嗎?圖資料庫和傳統概念上的「圖」不一樣,圖資料庫並不是儲存、分析美女帥哥圖片的資料庫,也不能批量PS自拍美顏照片,它和各種格式的圖片視頻沒有直接關係,也不能解決幾何圖形的問題,你問我心理陰影面積有多大?emmm……這麼大數易軒致力於圖資料庫技術服務,為您介紹圖資料庫的功能與作用。
  • 怎麼知道你的資料庫燒了多少錢?
    但事實是,在對資料庫的總成本進行定價時,還有很多事情要考慮。硬體和軟體成本仍然存在,但是你還需要考慮資料庫擴容,與現有和將來的系統集成,以及計劃內或計劃外停機的代價。 在對雲資料庫的成本進行定價時,至關重要的是事先提出這些問題。
  • 阿里雲POLARDB*:創新的雲託管資料庫
    然而,內部部署RDBMS就需要在基礎設施、時間、成本和人員方面大量投入,才能保持技術先進,可以根據業務增長需要進行擴展,還能實現數字轉型支持。關係型資料庫作為雲託管服務應用廣泛,稱為資料庫即服務(DBaaS)解決方案。但是基於雲的RDBMS可能本身存在難題。因此,雲託管關係型資料庫解決方案必須實現數字轉型。常見的資料庫有MySQL*和Oracle資料庫*,但不管是內部託管,還是雲託管,它們可能均難以保護、管理和擴展,而且可能達不到所需性能和服務質量(QoS)。
  • 中國地方志資料庫上線開放
    新華社武漢4月19日電(記者李偉)華中師範大學中國農村研究院建設的中國地方志資料庫19日正式上線向社會開放,該資料庫收錄量達31483冊,計82735卷。訪問者可通過標籤化處理,一鍵搜索獲取相關地方志資料,實現對資料的精確查詢。
  • 尹博學:百度分布式資料庫實踐與挑戰
    【IT168 技術】2012資料庫技術大會於4月13日在北京永泰朋福.喜來登酒店隆重召開。本次大會已經是IT168、ITPUB、IXPUB、ChinaUnix聯合主辦的第三屆資料庫技術會議。大會將針對大數據架構設計、資料庫安全、分布式資料庫、商業智能、NoSQL、Hadoop等多個重點話題進行深入探討。
  • Hello,圖資料庫!再見,DBA!
    1977年,矽谷一個30多歲的男人,憑藉IBM的一個「失誤」,成功開發了世界上使用最廣泛,最成功的關係型資料庫產品,就是後來的Oracle。到了1995年,IBM才發布了其關係型資料庫產品,DB2。
  • 圖資料庫如何在房地產行業場景進行應用
    OrientDB和ArangoDB它們起步比較早,最初的時候都是一個單機的圖資料庫,然後隨著用戶數據量的不斷增加,後期增加了分布式模式,支持集群和副本,但是經過調研發現,可能是由於後加的功能,他們的分布式支持的不是很好。
  • 大數據之HBASE資料庫
    HBase(Hadoop Database)是一個高可靠性、高性能、面向列、可伸縮的分布式資料庫,典型的 NoSQL資料庫。2010年5月,Apache HBase 從 Hadoop脫離,成為 Apache 基金的頂級項目。
  • 資料庫軟體架構,到底要設計些什麼?
    網際網路公司資料庫實際軟體架構是「既分片,又分組」:這種方法大家用的比較多,存在兩個缺點:(1)從庫越多,同步越慢;(2)同步越慢,數據不一致窗口越大;第三種增加系統讀性能的方式是,增加緩存。常見的緩存架構如下:
  • 頂級資料庫內核專家,為什麼選擇了這家上市公司?
    近期,海量數據研發團隊再添一名重量級專家——前Oracle中國研發中心高級研發總監李年加盟,任資料庫首席專家。李年畢業於清華大學,Oracle中國區資料庫研發最高負責人,國內資料庫內核的頂級專家。
  • 電子數據取證之MySQL資料庫刪除數據的恢復指南
    方法三:在存放資料庫的文件夾中是否存在mysql-bin.000001類似的文件,有則表示binlog日誌功能是開啟的。案例介紹:現有MySQL資料庫,其中有名為test的資料庫,其中沒有任何的表,懷疑數據被刪除,在該電腦中還發現了該資料庫的備份,備份最後被修改的時間為2018-11-21 15:27:12。目的:查看是否有刪除的操作,如有刪除嘗試恢復出刪除的表的內容。
  • SCP基金會離線資料庫nn5n
    SCP基金會離線資料庫nn5n 資訊閱讀 大小: 2.6 GB 版本: