MySQL案例之Timestamp和Datetime

来源:https://www.cnblogs.com/rangle/archive/2018/01/12/8275302.html
-Advertisement-
Play Games

mysql資料庫常用的時間類型有timestamp和datetime,兩者主要區別是占用存儲空間長度不一致、可存儲的時間也有限制,但針對不同版本下,timestamp欄位類型的設置需要慎重,因為不註意的可能會被“坑死”。 一、TIMESTAMP和DATETIME欄位類型對比 1.timestamp註 ...


mysql資料庫常用的時間類型有timestamp和datetime,兩者主要區別是占用存儲空間長度不一致、可存儲的時間也有限制,但針對不同版本下,timestamp欄位類型的設置需要慎重,因為不註意的可能會被“坑死”。

一、TIMESTAMP和DATETIME欄位類型對比

欄位類型 存儲長度 時間範圍 備註
timestamp 4位元組 '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC  
datetime 8位元組(5.7占5位元組) '1000-01-01 00:00:00' to '9999-12-31 23:59:59'  

 

 

 

1.timestamp註意事項

(1)5.7版本之前,沒有explicit_defaults_for_timestamp 參數(5.7預設開啟,timestamp不會設置default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP屬性),timestamp欄位預設存在default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP屬性,預設值針對的主要是以下函數產生的時間

These are CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, and LOCALTIMESTAMP().

(2)mysql的timestamp值自動從當前時區轉換到utc時區存儲,並且自動從utc時區轉換為當前系統時區檢索返回

官方參考文檔:https://dev.mysql.com/doc/refman/5.7/en/datetime.html

MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. 
(This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.

2.datetime註意事項:

在mysql5.7之後,datetime欄位也可以指定預設值,並且格式和timestamp一樣

CREATE TABLE t1 (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
或
DEFAULT 0 or DEFAULT '2000-01-01 00:00:00'

二、資料庫時區參數

1.system_time_zone

  資料庫實例啟動,從my.cnf配置參數timezone=timezone_name獲取,若my.cnf未設置則從操作系統獲取環境變數TZ獲取
2.time_zone

  資料庫當前實際使用的時區,預設為system,即系統時區,其設置可以通過set global time_zone=''設置,其中參數值有以下三種形式:'SYSTEM' 、'+10:00' 、'Europe/Helsinki'

Linux時區知識擴展:
Linux將時鐘分為系統時鐘(System Clock)和硬體(Real Time Clock,簡稱RTC)時鐘兩種。系統時間是指當前Linux Kernel中的時鐘,
而硬體時鐘則是主板上由電池供電的那個主板硬體時鐘,這個時鐘可以在BIOS的
"Standard BIOS Feture"項中進行設置。 系統時鐘: 所有操作系統命令、函數依賴的時鐘,獨立於硬體時鐘運行,可通過date設置 設置系統時間:date -s "2017-08-22 22:58:00" 查看時區:date -R 硬體時鐘: Linux啟動從系統配置獲取 查看硬體時鐘:clock --show 、 hwclock --show 設置硬體時鐘:hwclock/clock --set --date="月/日/年 時:分:秒" 系統時鐘同步到硬體:/sbin/clock -w 硬體時鐘同步到系統:/sbin/clock -s 時區設置: 修改/etc/sysconfig/clock ZONE=Asia/Shanghai rm /etc/localtime 鏈接到上海時區文件 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 執行完上述過程後,重啟機器,即可看到時區已經更改。

、實際使用實例

1.不同版本下timestamp和datetime使用實例

(1)測試timestamp和datetime創建帶預設值的表
同時執行創建帶預設值的SQL語句,發現5.6(不含5.6)之前版本datetime不支持帶DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

CREATE TABLE test (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

5.0
.67版本 ERROR 1067 (42000): Invalid default value for 'dt' 5.5.20版本 ERROR 1067 (42000): Invalid default value for 'dt' 5.6.22版本 Query OK, 0 rows affected (0.02 sec) 5.7.18版本 Query OK, 0 rows affected (0.00 sec)

(2)測試timestamp和datetime創建表結構類型

不指定預設值的情況下創建表結構,發現5.6(不含5.6)timestamp預設值是CURRENT_TIMESTAMP並且隨著記錄更新而更新

CREATE TABLE test01 (
  ts TIMESTAMP  ,
  dt DATETIME 
);

5.0.67版本
 CREATE TABLE `test01` (
  `ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `dt` datetime default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

5.5.20版本
 CREATE TABLE `test01` (
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
 
5.6.22版本
CREATE TABLE `test01` (
  `ts` timestamp NULL DEFAULT NULL,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

5.7.18版本
CREATE TABLE `test01` (
  `ts` timestamp NULL DEFAULT NULL,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

(3)、測試timestamp和datetime類型mysqldump導出導入影響

測試結論為,timestamp數據類型的記錄導出會以utc時間格式導出,導入庫中自動由UTC格式轉為系統預設時區,所以看到導出文件timestamp內容時間戳和實際存儲的不相符。

如果需要看到和導入與實際相符的時間戳,需要加入參數--tz-utc=false用於禁止timestamp時區轉換,預設是開啟的,即導出文件中開頭設置的/*!40103 SET TIME_ZONE='+00:00' */;

系統預設是cst時區,資料庫參數設置也是CST和SYSTEM,根據系統時間插入數據:

| system_time_zone | CST    |
| time_zone              | SYSTEM |

insert into test01 values(sysdate(),sysdate());

5.0.67版本
select * from test01;
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-12 14:15:19 | 2018-01-12 14:15:19 | 
+---------------------+---------------------+
 
5.5.20版本
select * from test01;
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-12 14:15:27 | 2018-01-12 14:15:27 |
+---------------------+---------------------+
 
5.6.22版本
select * from test01;
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-07 20:13:22 | 2018-01-07 20:13:22 |
+---------------------+---------------------+
 
5.7.18版本
select * from test01;
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-07 20:13:20 | 2018-01-07 20:13:20 |
+---------------------+---------------------+

然後將資料庫表test01表利用mysqldump導出

mysqldump dbtest --tables test01  >test01.sql
5.0.67版本
-- MySQL dump 10.11
--
-- Host: localhost    Database: dbtest
-- ------------------------------------------------------
-- Server version       5.0.67-percona-highperf-log
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `test01` (
  `ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `dt` datetime default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-12 06:15:19','2018-01-12 14:15:19');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on 2018-01-12  6:22:25 
5.5.20版本
-- MySQL dump 10.13  Distrib 5.5.20, for Linux (x86_64)
--
-- Host: localhost    Database: dbtest
-- ------------------------------------------------------
-- Server version       5.5.20-rel24.1-log

/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-12 06:15:27','2018-01-12 14:15:27');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on 2018-01-12 14:22:32
5.6.22版本
-- MySQL dump 10.13  Distrib 5.6.22-71.0, for Linux (x86_64)
--
-- Host: localhost    Database: dbtest
-- ------------------------------------------------------
-- Server version       5.6.22-71.0-log
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
  `ts` timestamp NULL DEFAULT NULL,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-07 12:13:22','2018-01-07 20:13:22');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on 2018-01-07 20:20:29
5.7.18版本
-- MySQL dump 10.13  Distrib 5.7.18-15, for Linux (x86_64)
--
-- Host: localhost    Database: dbtest
-- ------------------------------------------------------
-- Server version       5.7.18-15-log

/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
  `ts` timestamp NULL DEFAULT NULL,
  `dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-07 12:13:20','2018-01-07 20:13:20');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on 2018-01-07 20:20:29

刪除test01表,並用mysqldump導出文件還原

mysql -D dbtest -e "drop tables test01"
mysql -D dbtest  <test01.sql 
select * from test01;

5.0.67版本
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-12 14:15:19 | 2018-01-12 14:15:19 | 
+---------------------+---------------------+
5.5.20版本
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-12 14:15:27 | 2018-01-12 14:15:27 |
+---------------------+---------------------+
5.6.22版本
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-07 20:13:22 | 2018-01-07 20:13:22 |
+---------------------+---------------------+
5.7.18版本
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2018-01-07 20:13:20 | 2018-01-07 20:13:20 |
+---------------------+---------------------+

(4)ON UPDATE CURRENT_TIMESTAMP屬性影響

如果包含ON UPDATE CURRENT_TIMESTAMP屬性,則如果對錶記錄更新,此記錄對應的timestamp類型記錄也會更新

ts欄位是timestamp類型且含有on update current_timestamp屬性,dt欄位是datetime類型且不含on update current_timestamp屬性
更新前:
mysql -D dbtest -e "select * from test01;"
+---------------------+---------------------+------+
| ts                  | dt                  | id   |
+---------------------+---------------------+------+
| 2018-01-12 14:15:19 | 2018-01-12 14:15:19 | NULL | 
+---------------------+---------------------+------+
更新:
mysql -D dbtest -e "update test01 set id=1 where id is null"
更新後:
mysql -D dbtest -e "select * from test01;"                  
Logging to file '/home/mysql/query.log'
+---------------------+---------------------+------+
| ts                  | dt                  | id   |
+---------------------+---------------------+------+
| 2018-01-12 15:42:15 | 2018-01-12 14:15:19 |    1 | 
+---------------------+---------------------+------+

2.不同版本下mysqldump結束時間分析

使用mysqldump備份的同仁都可能會註意到,正常備份結束的話,在文件結尾會有一條成功結束的表示,即 :-- Dump completed on 2018-01-12  6:22:25。

這個在mysql5.0後可以通過一些參數控制,例如可以加參數--comments=false來禁止添加comments信息,即所有--開頭的comment會不記錄在備份文件中,也可以增加--dump-date=false來禁止時間戳添加,即只包含-- Dump completed。

但特別需要註意的是,此時間戳的由來在mysqldump 10.11版本(mysql5.0.x版本對應MySQL dump 10.11, 含10.11版本)記錄的是UTC時區時間戳,而在mysqldump 10.12版本之後(mysql 5.5對應的版本是MySQL dump 10.13,含10.13)記錄的是系統當前時區時間戳。

所以大家看到的是mysqldump 10.11備份結束的時間總是比系統當前時間提前8小時,例如mysql5.0系統當前是CST時區:2018-01-12  14:22:25   而備份文件結束時間戳是-- Dump completed on 2018-01-12  6:22:25。這個只是記錄的時間戳不同,不影響最終的數據記錄時間。

源碼片段如下:

./client/mysqldump.c

#define DUMP_VERSION "10.13"

static void write_footer(FILE *sql_file)
{
  if (opt_xml)
  {
    fputs("</mysqldump>\n", sql_file);
    check_io(sql_file);
  }
  else if (!opt_compact)
  {
    if (opt_tz_utc)
      fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");

    fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n");
    if (!path)
    {
      fprintf(md_result_file,"\
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
    }
    if (opt_set_charset)
      fprintf(sql_file,
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
    fprintf(sql_file,
            "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
    fputs("\n", sql_file);

    if (opt_dump_date)
    {
      char time_str[20];
      get_date(time_str, GETDATE_DATE_TIME, 0);
      print_comment(sql_file, 0, "-- Dump completed on %s\n", time_str);
    }
    else
      print_comment(sql_file, 0, "-- Dump completed\n");

    check_io(sql_file);
  }
} /* write_footer */

get_date()函數是核心,那麼其源碼./mysys/mf_getdate.c如下:

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、關機/重啟 1、shutdown命令 shutdown 命令可以安全關閉或者重新啟動系統 -r 重新啟動 PS(不指定選項和參數,預設表示1分鐘之後關閉電腦) 遠程維護伺服器時,最好不要關閉系統(即 加上-r),而應該重新啟動系統 常用命令實例 #重新啟動操作系統,其中 now 表示現在 $sh ...
  • 操作系統 : CentOS7.3.1611_x64 go語言版本:1.8.3 linux/amd64 InfluxDB版本:1.1.0 influxdb預設配置: meta預設配置: dir meta數據存放目錄,預設值:/var/lib/influxdb/meta meta數據文件預設路徑:/va ...
  • 1、首先要準備好安裝文件oracle11 2、在oracle11文件夾中找到setup.exe,雙擊運行 3、在配置安全更新中,輸入常用的電子郵件(非必填) 4、點擊下一步進入到“安裝選項“,預設選擇創建和配置資料庫 5、點擊”下一步“,選擇”伺服器類“ 6、點擊”下一步“,不進行任何修改 7、點擊 ...
  • mysql命令不區分大小寫。內容,表名什麼的是區分大小寫的。 語句以(;)結束。(\c)結束不想執行正在輸入的命令。(命令+ \G;)查看詳細結構 啟動/停止/重啟:server mysql start/stop/restart /etc/init.d/mysql start/stop/restar ...
  • IF OBJECT_ID('fn_GetChnNum') IS NOT NULL BEGIN DROP FUNCTION dbo.fn_GetChnNum; END; GO CREATE FUNCTION fn_GetChnNum ( @Number AS BIGINT )RETURNS VARCH ...
  • 1.應用場景和特點 hbase => 當數據量非常大的時候才會體現出hbase的優勢 特點: 海量數據存儲 => 單表可有上百億行。上百萬的列。也就是對列沒有限制。 => 關係型資料庫正常單表不超過五百萬行,不超過三十列。 面向列 => 動態添加數據的時候生成列。單獨對列進行各種操作。 多版本 稀疏 ...
  • 資料庫中left join,right join,inner join的差異 ...
  • 一 所需軟體:Redis、Ruby語言運行環境、Redis的Ruby驅動redis-xxxx.gem、創建Redis集群的工具redis-trib.rb 二 安裝配置redis redis下載地址 https://github.com/MSOpenTech/redis/releases ; 下載Re ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...