MYSQL和ORACLE時區設定比較

gaopengtttt發表於2015-09-18
MYSQL:
注意時區會影響TIMESTAMP的取值,預設為系統時區為TIME_ZONE=SYSTEM,
動態可以修改
set global  time_zone = '+8:00'; 

然後
my.cnf加上,永久修改
default-time_zone = '+8:00' 

The current time zone. This variable is used to initialize the time zone for each client that
connects. By default, the initial value of this is 'SYSTEM'(which means, “use the value of
system_time_zone”). 
也就是說每個連結都會使用這個引數作為他的預設時區,而TIMESTMAP是根據客戶端的時區不同
而不同,所以如果如果這個引數設定有誤會導致TIMESTAMP時間出現問題

MYSQL的測試:
mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2015-06-12 12:10:13 |
+---------------------+
1 row in set (0.00 sec)


mysql> select sysdate();
+---------------------+
| sysdate()           |
+---------------------+
| 2015-06-12 12:10:18 |
+---------------------+
1 row in set (0.00 sec)


mysql> select current_timestamp from dual;
+---------------------+
| current_timestamp   |
+---------------------+
| 2015-06-12 12:10:46 |
+---------------------+
1 row in set (0.00 sec)


mysql> set time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)


mysql> select sysdate();
+---------------------+
| sysdate()           |
+---------------------+
| 2015-06-12 04:11:01 |
+---------------------+
1 row in set (0.00 sec)


mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2015-06-12 04:11:04 |
+---------------------+
1 row in set (0.00 sec)


mysql> select current_timestamp from dual;
+---------------------+
| current_timestamp   |
+---------------------+
| 2015-06-12 04:11:06 |
+---------------------+
1 row in set (0.01 sec)

可見MYSQL的NOW(),SYSDATE(),current_timestamp 均跟著客戶端時區走的。

oracle:
另外說一下ORACLE的時區問題,ORACLE時區分為
dbtimezone和sessiontimezone
其中DBTIMEZONE只和TIMESTAMP WITH LOCAL TIME ZONE有關,在TIMESTAMP WITH LOCAL TIME ZONE型別存入資料庫中,實際上是轉換為DBTIMEZONE的時間,取出的時候
自動加上客戶端的SESSIONTIMEZONE的偏移量,文件如下:

TimeStamp with Local Time Zone (TSLTZ) data stores internally the time converted to/from the database timezone (see point 3) from the timezone specified at insert/select time. 

Note that the data stored in the database is normalized to the database time zone, and the time zone offset is not stored as part of the column data, the current DBTIMZONE is used. When users retrieve the data, Oracle Database returns it in the users' local session time zone from the current DBTIMEZONE.


而其他的時間型別和DBTIMEZONE無關,這也是為什麼有了TIMESTAMP WITCH LOCAL TIME ZONE修改DBTIMEZONE不行的原因,因為如果修改了DBTIMEZONE會導致時間錯誤。
實際上MYSQL的TIMESTAMP型別和ORACLE的TIMESTAMP WITCH LOCAL TIME ZONE型別都是根據客戶端的時間來進行返回時間,但是MYSQL可以簡單的設定
 time_zone引數來改變所有連線的時區,這樣返回的時間能夠正確。
在說明一下ORACLE的TIMESTAMP和MYSQL的TIMESTAMP完全不同,
ORACLE的TIMESTAMP是為了精確到秒後6位,
而MYSQL的TIMESTAMP是為了更少的儲存單元(DATETIME為4位元組,TIMESTAMP為1個位元組)但是範圍為1970的某時的開始到2037年,而且會根據客戶端的時區判斷返回值

sessiontimezone,則影響著客戶端的時區,TIMESTAMP WITCH LOCAL TIME ZONE也會跟著這個時區進行改變,其他資料型別如DATE,TIMESTAMP等不會受到影響
可以再ALTER SESSION中設定也可以設定環境變數TZ=
如:
ALTER SESSION SET TIME_ZONE = '-05:00';
或者
export TZ='Asia/Shanghai';

做個簡單的實驗

SQL> desc testtim;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DATE1                                              TIMESTAMP(6)
 DATE2                                              TIMESTAMP(6) WITH TIME ZONE
 DATE3                                              TIMESTAMP(6) WITH LOCAL TIME ZONE
SQL> select * from testtim;

DATE1
---------------------------------------------------------------------------
DATE2
---------------------------------------------------------------------------
DATE3
---------------------------------------------------------------------------
12-JUN-15 11.40.02.000000 AM
12-JUN-15 11.40.02.000000 AM +08:00
12-JUN-15 11.40.02.000000 AM


SQL> alter SESSION SET TIME_ZONE = '-05:00';

Session altered.

SQL> select * from testtim;

DATE1
---------------------------------------------------------------------------
DATE2
---------------------------------------------------------------------------
DATE3
---------------------------------------------------------------------------
12-JUN-15 11.40.02.000000 AM
12-JUN-15 11.40.02.000000 AM +08:00
11-JUN-15 10.40.02.000000 PM


最後ORACLE中常用的取時間函式的不同:

LOCALTIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP, that is date time similar to CURRENT_DATE but the datatype is TIMESTAMP.

CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE, that is date time similar to CURRENT_DATE but the datatype is TIMESTAMP WITH TIME ZONE.

SYSTIMESTAMP returns the system date, including fractional seconds and time zone, of the system on which the database resides. The return type is TIMESTAMP WITH TIME ZONE. Unlike SYSDATE, which you can set to a constant using FIXED_DATE, SYSTIMESTAMP will give the system date even though FIXED_DATE is set.

"SYSDATE" and "SYSTIMESTAMP" are purely dependent on the operating system clock, hence it IS depending on the timezone information of this operating system and/or the operating system settings when the database and listener where started.

很顯然LOCALTIMESTAMP和CURRENT_TIMESTAMP都受到客戶端SESSIONTIMEZONE影響,而SYSDATE的不受影響他返回的一定是伺服器ORACLE 設定的SESSIONTIMEZONE的時間。
如果需要更改客戶端的SYSDATE的取值必須
1、修改伺服器下ORACLE使用者的TZ
2、重啟資料庫

如:

export  TZ='UTC';
後檢視服務端SYSDATE
SQL> select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual;


TO_CHAR(SYSDATE,'YY
-------------------
2015-06-12 04:06:34
按理說客戶端也應該返回這個值
但是客戶端任然返回

SQL> select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
------------------------------
2015-06-12 12:08:19

重啟後
SQL> select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
------------------------------
2015-06-12 04:09:19

客戶端正常。

總結一下:
1、ORACLE和MYSQL的timestamp不同
ORACLE的TIMESTAMP是為了精確到秒後6位,
而MYSQL的TIMESTAMP是為了更少的儲存單元(DATETIME為4位元組,TIMESTAMP為1個位元組)但是範圍為1970的某時的開始到2037年,而且會根據客戶端的時區判斷返回值
MYSQL的TIMESTAMP時區敏感這點和ORACLE的TIMESTAMP WITH LOCAL TIME ZONE一致。
2、ORACLE和MYSQL的函式返回不一樣
ORACLE:
LOCALTIMESTAMP和CURRENT_TIMESTAMP都受到客戶端SESSIONTIMEZONE影響,而SYSDATE,SYSTIMESTAP的不受影響他返回的一定是伺服器ORACLE 設定的SESSIONTIMEZONE的時間
MYSQL:
NOW(),SYSDATE(),
CURRENT_TIMESTAMP 均受到客戶端連線時區影響。

3、oracle的DBTIMEZONE用處不大,只和TIMESTAMP WITH LOCAL TIME ZONE有關。
4、為了返回一致的資料MYSQL設定TIME_ZONE引數即可因為他是每個連線都會用到的,但是ORACLE最好使用SYSDATE或者SYSTIMESTAMP來直接取服務端的SESSIONTIMEZONE下的時間。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-1802858/,如需轉載,請註明出處,否則將追究法律責任。

相關文章