mysql默认时区:
mysql> show variables like '%time_zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | PDT | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.01 sec)
my.cnf配制文件修改: 可以通过修改my.cnf 在 [mysqld] 之下加 default-time-zone=timezone 来修改时区。如: default-time-zone = '+8:00'
通过命令:
set time_zone = timezone 比如北京时间(GMT+0800) set time_zone = '+8:00';
美国pst时间(GMT-08:00) set time_zone = '-8:00';
eg:
mysql> set time_zone = '+8:00'; Query OK, 0 rows affected (0.17 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2016-06-23 16:32:53 | +---------------------+ 1 row in set (0.00 sec) mysql> set time_zone = '-8:00'; Query OK, 0 rows affected (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2016-06-23 00:33:21 | +---------------------+ 1 row in set (0.00 sec)
mysql 数据库中的时区信息默认为空:
mysql> show tables like "%time%";
+---------------------------+
| Tables_in_mysql (%time%) |
+---------------------------+
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
+---------------------------+
5 rows in set (0.00 sec)
导入时区信息到MYSQL中
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
查看导入后的信息:
mysql> SELECT * FROM time_zone_name WHERE name LIKE 'America/%' limit 10; +----------------------------------+--------------+ | Name | Time_zone_id | +----------------------------------+--------------+ | America/Adak | 54 | | America/Anchorage | 55 | | America/Anguilla | 56 | | America/Antigua | 57 | | America/Araguaina | 58 | | America/Argentina/Buenos_Aires | 59 | | America/Argentina/Catamarca | 60 | | America/Argentina/ComodRivadavia | 61 | | America/Argentina/Cordoba | 62 | | America/Argentina/Jujuy | 63 | +----------------------------------+--------------+ 10 rows in set (0.00 sec)
美国不仅有时区,还有夏令时,冬令时,提前一小时,或者减慢一小时(在时区时间基础上)
美国2016年夏令时将于2016年03月13日当地时间早上02:00(北京时间14:00)开始,至2016年11月6日结束,届时美国的交易时间将较冬令时提前1个小时
mysql> SELECT CONVERT_TZ('2016-03-13 01:30:00','-8:00','America/Los_Angeles') AS TIMEG *************************** 1. row *************************** TIME: 2016-03-13 01:30:00 1 row in set (0.00 sec)
mysql> SELECT CONVERT_TZ('2016-03-13 02:30:00','-8:00','America/Los_Angeles') AS TIMEG
*************************** 1. row ***************************
TIME: 2016-03-13 03:30:00
1 row in set (0.00 sec)
内核专家:
目前在MySQL数据库中,在初始化time_zone相关表元信息以后,MySQL就可以自己完成夏令时(Daylight Saving Time)和闰秒(Leap Second)的修正,不需要额外的服务器
高手:
设置timezone后,不需要再通过__tz_convert()来转换,各个线程之间并无锁冲突, now()的影响将微乎其微。性能自然获得大大提升。
公司有人实验过,高并发下now()性能有8倍之差。
NOW()函数 不设时区信息需要__tz_convert()进行转换,带时区信息NOW(),就不需要__tz_convert()进行转换
now()不带时区转换过程:
now()或current_timestamp()等获取带有时区信息的时间时,数据库会在server层解析填充其field时,
通过内核层将gmt时间转化为所需的time类型。而转换是通内核层的libc动态库的接口__tz_convert()来实现。
这个实现一个致命的缺点是:串行化
select now();
Breakpoint 2, 0x00007f50e68a5ab0 in __tz_convert () from /lib64/libc.so.6 (gdb) bt #0 0x00007f50e68a5ab0 in __tz_convert () from /lib64/libc.so.6 #1 0x00000000008a40ef in Time_zone_system::gmt_sec_to_TIME (this=0x180ee30 <tz_SYSTEM>, tmp=0x48e0830, t=1467609071) at /usr/src/mysql-5.6.28/sql/tztime.cc:1079 #2 0x00000000006e9ce0 in Time_zone::gmt_sec_to_TIME (this=0x180ee30 <tz_SYSTEM>, tmp=0x48e0830, tv=...) at /usr/src/mysql-5.6.28/sql/tztime.h:60 #3 0x00000000006e5e61 in MYSQL_TIME_cache::set_datetime (this=0x48e0830, tv=..., dec_arg=0 '