问题概述
阿里云本RDS在本地的从库,主从复制过程中报错:Last_Errno 1298; Last_Error: "Unknown or incorrect time zone: “Asia/Shanghai”’ on query. Default database: "XXX’. Query: “BEGIN”
截图如下:
查询本地从库信息:
root@localhost:(none) 10:32:40 >show global variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | +08:00 |
+------------------+--------+
## 说明:本地从库时区为东八区 +08:00
本地从库时区就是东八区,与错误提示中Asia/Shanghai是同一个时区,但是错误提示中看出,MySQL数据库无法识别Asia/Shanghai,推测MySQL系统内部无法进行Asia/Shanghai到 +08:00 的转换 导致出现错误,通过设置来做验证:
root@localhost:(none) 10:19:49 >set globaltime_zone='Asia/Shanghai';
ERROR 1298 (HY000): Unknown or incorrect time zone: 'Asia/Shanghai'
## 果然,MySQL内部无法进行时区的转换,也无法设置文字时区。
问题原因
MySQL默认不支持’Asia/Shanghai’这种时区格式,故在SQL执行中如果有SQL或者存储过程进行对时区的设置,涉及到文字时区转换时,就会报错。
解决方案
访问官方地址:
https://dev.mysql.com/downloads/timezones.html
下载时区文件
下载后解压执行timezone_posix.sql 即可:
mysql -u root -ppassword
use mysql;
source /full/path_to_sqlfile/timezone_posix.sql
由于我们本地从库为5.6版本,目前官方地址并没有给出5.6版本的相关脚本路径,只有5.7以上版本的,故担心版本问题没有执行,从而选择另外一种方式进行尝试:
参考命令:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot mysql -p
实际命令:
/data/mysql/mysql8034/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | /data/mysql/mysql8034/bin/mysql -uroot -pmysql mysql --socket=/data/mysql/8034/run/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
命令说明:
mysql_tzinfo_to_sql是MySQL自带的命令程序,在MySQL软件的bin目录中可以查到,该命令的作用就是来填充MySQL 时区表(一次加载操作系统支持的所有时区),mysql_tzinfo_to_sql命令会读取您系统的时区文件并生成SQL语句来插入到MySQL的时区表中。注意:这种方式不会导入跳秒信息到time_zone_leap_second表中,需要单独操作。
## 说明:命令执行完毕后,发现 MySQL库下面的对应表都有数据了,执行执行是没有数据的:
root@localhost:mysql 11:03:13 >select count(*) from time_zone;
+----------+
| count(*) |
+----------+
| 1783 |
+----------+
1 row in set (0.00 sec)
root@localhost:mysql 11:03:21 >select count(*) from time_zone_name;
+----------+
| count(*) |
+----------+
| 1783 |
+----------+
1 row in set (0.00 sec)
root@localhost:mysql 11:03:26 >select count(*) from time_zone_transition;
+----------+
| count(*) |
+----------+
| 118825 |
+----------+
1 row in set (0.00 sec)
root@localhost:mysql 11:03:35 >select count(*) from time_zone_transition_type;
+----------+
| count(*) |
+----------+
| 8728 |
+----------+
1 row in set (0.00 sec)
## 最后通过设置时区,也不再报错,
root@localhost:mysql 11:03:49 >set global time_zone='Asia/Shanghai';
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql 11:08:37 >show variables like '%time_zone%';
+------------------+---------------+
| Variable_name | Value |
+------------------+---------------+
| system_time_zone | CST |
| time_zone | Asia/Shanghai |
+------------------+---------------+
2 rows in set (0.00 sec)
root@localhost:mysql 11:08:39 >set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql 11:09:07 >show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | +08:00 |
+------------------+--------+
2 rows in set (0.00 sec)
至此问题解决,重新启动从库复制进程,同步正常:
mysql> stop slave;
mysql> start slave;
mysql> show slave statusG
Slave_IO Running:Yes
Slave_SQL_Running:Yes
Last_Error:
Seconds Behind Master:0
Retrieved_Gtid_Set:05ec2ca4-67d1-1lee-a27e-506b4b2f585c:13566-14338
Executed_Gtid_Set:05ec2ca4-67d1-1lee-a27e-506b4b2f585c:1-14338
## 从库同步状态正常,双YES,无报错,无延迟
参考文档
https://dev.mysql.com/downloads/timezones.html
https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html