沃趣科技作为国内领先的数据库云平台解决方案提供商,一直致力于企业级数据库云平台产品的研发,为用户提供高性能、高可用、可扩展的的数据库云环境及不同业务场景需求的数据库平台,满足客户对极致性能、数据安全、容灾备份、业务永续等需求。沃趣科技凭借专业的团队,优质的产品,前沿的技术,贴心的服务赢得了客户的信任与尊重,也获得了市场的认同。
之前文章(引用沃趣技术--《当心!使用mysqldump备份可能会让你欲哭无泪》)介绍了当时间字段为timestamp时,使用mysqldump加where条件对时间字段进行过滤导出时,时域问题对导出数据的影响。今天我们就再来讨论一下mysqldump的时域问题。
问题介绍
日前,在客户某系统部署了一个数据清理脚本,该脚本在对数据进行清理之前,首先会按照清理数据的条件先使用mysqldump将即将清理的数据导出,再进行清理。该脚本使用crontab定时任务在凌晨两点执行。但第二天查看脚本的执行情况时,发现数据清理工作都顺利的完成了,但mysqldump导出的SQL文件里却只导出了表结构,没有导出数据。看到这个现象甚是奇怪。
问题分析与排查
-
查看导出数据的where条件为"gmt_modified < date_sub(curdate(),interval 359 day)",基于之前的理解,我们想过有可能是时域的问题,所以确认了一下gmt_modified字段的数据类型,查看确认gmt_modified的数据类型为datetime,由于datetime数据类型是与时域无关的,所以针对这一问题,排除了时域对导出数据的影响。
-
难道是这个脚本在当前服务器的环境问题?将导出数据的条件改为"gmt_modified < date_sub(curdate(),interval 358 day)",在这个条件下会查询出一天的数据,将脚本当中的数据删除部分注释掉,只执行数据导出的部分,发现该脚本完整的导出了数据。实在让人疑惑,为什么白天上班的时候数据能够备份出来,然而凌晨的时候数据就备不出来?
-
这时候,怀疑是不是当时数据库处于某种状态,阻止了mysqldump的备份。于是写了一个脚本,每隔一秒去检测当前数据库的连接状态。加入crontab,与删除数据的脚本在凌晨同时调起。数据清理脚本大约1分钟执行完成,于是设定数据库连接监控脚本执行3分钟。第二天观察监控的日志,也并未发现有任何异常的连接。
-
手动执行脚本能够备份成功,crontab就无法备份,难道真的有什么鬼故事?于是在凌晨2点手动执行备份脚本,发现的确无法备份。将脚本当中的mysqldump语句摘录出来,单独执行,仍然没有备份成功。看来备份失败与脚本、与环境都没有关系,就是mysqldump的问题。又回到问题的起点,难道真的是时域惹的祸?于是在mysqldump时加上--skip-tz-utc的参数。执行备份,这次备份成功了。
--skip-tz-utc参数介绍
为什么--skip-tz-utc参数会影响mysqldump导出的时域呢,下面先简要介绍一下--skip-tz-utc这个参数。
在mysql服务器上执行mysqldump --help的命令,可以看到下面一段话。
--tz-utc SET TIME_ZONE='+00:00' at top of dump to allow dumping of
TIMESTAMP data when a server has data in different time
zones or data is being moved between servers with
different time zones.
(Defaults to on; use --skip-tz-utc to disable.)
--tz-utc参数是mysqldump的默认参数,会使得mysqldump的导出文件的顶部加上一个设置时域的语句SET TIME_ZONE='+00:00',这个时域是格林威治时间,这样当导出timestamp字段时,会把在服务器设置的当前时域下显示的timestamp时间值转化为在格林威治时间下显示的时间。如下图所示,mysqldump导出的文件当中显示的时间值相对于通过数据库查询显示的时间倒退了8个小时。
mysql> show variables like "time_zone";
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| time_zone | +08:00 |
+---------------+--------+
1 row in set (0.01 sec)
mysql> show create table t_timestamp;
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_timestamp | CREATE TABLE `t_timestamp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_bin NOT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COLLATE=utf8_bin |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t_timestamp;
+----+-----------+---------------------+
| id | name | create_time |
+----+-----------+---------------------+
| 1 | messi | 2019-12-07 13:27:55 |
| 3 | xavi | 2019-12-07 13:28:01 |
| 5 | xsh | 2019-12-07 13:28:08 |
| 7 | cr7 | 2019-12-08 14:24:18 |
| 9 | ozil | 2019-12-08 14:24:26 |
| 11 | ramos | 2019-12-08 14:24:33 |
| 13 | pique | 2019-12-09 08:24:24 |
| 15 | henry | 2019-12-09 08:24:34 |
| 17 | lukaku | 2019-12-10 12:00:58 |
| 19 | rakitici | 2019-12-10 12:01:12 |
| 21 | van dijk | 2019-12-11 22:00:46 |
| 23 | mane | 2019-12-11 22:00:57 |
| 25 | suarez | 2019-12-11 22:01:34 |
| 27 | Ronaldol | 2019-12-11 22:01:55 |
| 29 | Ronaldiho | 2019-12-12 18:00:20 |
| 31 | Deco | 2019-12-12 18:00:28 |
+----+-----------+---------------------+
16 rows in set (0.00 sec)
[root@rhel74 timestamp]# mysqldump --single-transaction -uroot -p123456 -S /home/mysql/data/mysqldata1/sock/mysql.sock --set-gtid-purged=OFF xshtest t_timestamp > full_timestamp.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@rhel74 timestamp]# vim full_timestamp.sql
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHAR