日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时...

發布時間:2023/12/4 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

#?為什么存入mysql數據庫中的timestamp,晚了13個小時

##?查看數據庫時區

```

show?variables?like?'%time_zone%';

select?@@global.system_time_zone;

select?@@global.time_zone;

可以得到默認數據庫時區:

system_time_zone?|?CST?|

time_zone?|?SYSTEM|

```

##?CST時區:4個含義

>CST可以為如下4個不同的時區的縮寫:

>1,美國中部時間:Central?Standard?Time?(USA)?UT-6:00?,又美國從“3月11日”至“11月7日”實行夏令時,美國中部時間改為?UT-05:00

>2,澳大利亞中部時間:Central?Standard?Time?(Australia)?UT+9:30

>3,中國標準時間:China?Standard?Time?UT+8:00

>4,古巴標準時間:Cuba?Standard?Time?UT-4:00

>PS:即中國標準時間UT+8,和美國UT-5,中間相差13個小時

##?查看java程序運行的本地時區

```

TimeZone.getDefault();//得到"Asia/Shanghai"

```

##?debug與源碼分析:

>1,測試發現,客戶端到java程序端的時間戳是正確的,即通過mybatis寫入數據庫之前時間戳是正確的

>2,**從mybatis一路跟蹤:mybatis?SqlTimestampTypeHandler.setNonNullParameter()->mybatis?PreparedStatement.setTimestamp-》mysql-connector preparedStatement.setTimestamp()-》preparedStatement.setTimestampInternal()-》TimeUtil.changTimestamp(),通過計算本地時區和數據庫時區差值,得到數據的時間戳,再轉成SimpleDateFormat.format?yyyy-MM-dd?HH:mm:ss格式的時間戳日期字符串,寫入數據庫**

>3,問題:java運行的本地時區是"Asia/Shanghai",那mysql-connector得到的數據庫時區是什么樣的?連接數據庫的時候,mysql-connector會獲取數據庫的時區信息,如上數據庫時區查詢,得到SYSTEM,CST

##?mysql-connector獲取數據庫時區

>1,CST?的時區是一個很混亂的時區,在與?MySQL?協商會話時區時,Java?會誤以為是?CST?-0500,而非?CST?+0800

```

private?void?configureTimezone()?throws?SQLException?{

String?configuredTimeZoneOnServer?=?(String)?this.serverVariables

.get("timezone");

if?(configuredTimeZoneOnServer?==?null)?{

configuredTimeZoneOnServer?=?(String)?this.serverVariables

.get("time_zone");

if?("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer))?{

configuredTimeZoneOnServer?=?(String)?this.serverVariables

.get("system_time_zone");//得到CST,mysql-connector以為的CST是美國的CST-5:00

}

}

...

}

```

>2,TimeZone.getTimeZone(canonicalTimezone)得到CST,mysql-connector以為的CST是美國的CST-5:00,{"CST",?"America/Chicago"}

>3,mysql-connector?ZoneInfoFile?class時區簡寫和時區對應關系

```

{{"ACT",?"Australia/Darwin"},

{"AET",?"Australia/Sydney"},

{"AGT",?"America/Argentina/Buenos_Aires"},

{"ART",?"Africa/Cairo"},

{"AST",?"America/Anchorage"},

{"BET",?"America/Sao_Paulo"},

{"BST",?"Asia/Dhaka"},

{"CAT",?"Africa/Harare"},

{"CNT",?"America/St_Johns"},

{"CST",?"America/Chicago"},

{"CTT",?"Asia/Shanghai"},

{"EAT",?"Africa/Addis_Ababa"},

{"ECT",?"Europe/Paris"},

{"IET",?"America/Indiana/Indianapolis"},

{"IST",?"Asia/Kolkata"},

{"JST",?"Asia/Tokyo"},

{"MIT",?"Pacific/Apia"},

{"NET",?"Asia/Yerevan"},

{"NST",?"Pacific/Auckland"},

{"PLT",?"Asia/Karachi"},

{"PNT",?"America/Phoenix"},

{"PRT",?"America/Puerto_Rico"},

{"PST",?"America/Los_Angeles"},

{"SST",?"Pacific/Guadalcanal"},

{"VST",?"Asia/Ho_Chi_Minh"}};

```

##?如何解決

###?一,修改數據庫時區

```

set?global?time_zone?=?'+8:00';//設置全局時區為東八區

set?time_zone?=?'+8:00';?//

flush?privileges;//刷新權限使設置立即生效

```

###?二,添加jdbc參數:serverTimezone=GMT%2B8

```

db?useUnicode=true&characterEncoding=UTF-8&useAffectedRows=true&useTimezone=true&serverTimezone=GMT%2B8

```

##?會有什么問題

>1,因為老數據是基于CST-5:00,得到的時間戳日期字符串(yyyy-MM-dd?HH:mm:ss.SSS),寫入數據庫中,改了數據庫時區或修改了JDBC的時區配置,會導致舊數據比以前慢13個小時

##?那舊數據怎么辦

>1,創建一個mybatis?TimstampTypehandler專門處理timestamp類型,將某個時間以前的時間戳加上13個小時的時間戳間隔,即可

```

@MappedJdbcTypes(JdbcType.TIMESTAMP)

@MappedTypes(Timestamp.class)

public?class?TimestampHandler?extends?SqlTimestampTypeHandler?{

@Override

public?void?setNonNullParameter(PreparedStatement?ps,?int?i,?Timestamp?parameter,?JdbcType?jdbcType)

throws?SQLException?{

ps.setTimestamp(i,?parameter);

}

@Override

public?Timestamp?getNullableResult(ResultSet?rs,?String?columnName)

throws?SQLException?{

//TimeZone?tz=TimeZone.getDefault();

//TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp?timestampTemp=rs.getTimestamp(columnName);

long?lt=timestampTemp.getTime();

long?timestampSplit=1590249600000L;//2020-05-24?00:00:00的毫秒時間戳

if(timestampSplit>lt){

Timestamp?timestamp=new?Timestamp(lt+13*60*60*1000);

return?timestamp;

}else{

return?timestampTemp;

}

}

@Override

public?Timestamp?getNullableResult(ResultSet?rs,?int?columnIndex)

throws?SQLException?{

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp?timestampTemp=rs.getTimestamp(columnIndex);

long?lt=timestampTemp.getTime();

long?timestampSplit=1590249600000L;//2020-05-24?00:00:00的毫秒時間戳

if(timestampSplit>lt){

Timestamp?timestamp=new?Timestamp(lt+13*60*60*1000);

return?timestamp;

}else{

return?timestampTemp;

}

}

@Override

public?Timestamp?getNullableResult(CallableStatement?cs,?int?columnIndex)

throws?SQLException?{

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

Timestamp?timestampTemp=cs.getTimestamp(columnIndex);

long?lt=timestampTemp.getTime();

long?timestampSplit=1590249600000L;//2020-05-24?00:00:00的毫秒時間戳

if(timestampSplit>lt){

Timestamp?timestamp=new?Timestamp(lt+13*60*60*1000);

return?timestamp;

}else{

return?timestampTemp;

}

}

}

```

##?多人開發,timestamp時間戳使用規約

>1,接口參數涉及時間,都用時間戳,精確到秒或毫秒,全項目統一

>2,時間戳參數直接入庫,不要在代碼層再做一次SimpleDateFormat.format?yyyy-MM-dd?HH:mm:ss.SSS轉換,這樣會附加本地時區,導致時間戳失效,mysql?connector在入庫前對timestamp類型做了本地時區和數據庫時區差值計算的

總結

以上是生活随笔為你收集整理的mysql数据库时间突然是12小时制_为什么存入mysql数据库中的timestamp,晚了13或14个小时...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。