复现
来源于一个同事在做数据转储碰到的的问题,简化如下:
1、建表
drop table if exists tb;
CREATE TABLE tb (
c timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
insert into tb values(now());
select * from tb;
返回
mysql> select * from tb;
+---------------------+
| c |
+---------------------+
| 2012-12-14 00:42:45 |
+---------------------+
1 row in set (0.00 sec)
2、dump“出错”
mysqldump -Srun/mysql.sock -uroot test tb --where='c="2012-12-14 00:42:45"' | grep INSERT
返回为空,也就是说导不到数据。
分析
从上面的结论看上去,似乎是mysqldump的”bug”,看得到的数据都导不出来。 如果我们先不加where条件,
mysqldump -Srun/mysql.sock -uroot test tb |grep INSERT
INSERT INTO `tb` VALUES ('2012-12-13 16:42:45');
接下来我们要说说关于timestamp这个字段类型。
首先,从大小上你可以看出来,它不是个字符串,实际上是一个整型。所以当我们执行 where c=” 2012-12-14 00:42:45”的时候,需要将其转换为整型。这就涉及到转换规则。也就是说,对于相同的时间戳,在不同的时区显示的结果是不一样的。反过来也一样,相同的字符串,在不同的时区解释下,会得到不同的时间戳。
我们来看一下整个mysqldump的结果。在文件头部,可以看到
/*!40103 SET TIME_ZONE='+00:00' */; 字样,说明mysqldump在默认情况下,是按’+00:00’(中时区).
而mysql客户端的默认值呢:
mysql> select @@time_zone;
+-------------+
| @@time_zone |
+-------------+
| SYSTEM |
+-------------+
这个SYSTEM表示MySQL取操作系统的默认时区,因此是东8区。如果我们设置为与mysqldump相同时区,
mysql> set time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tb;
+---------------------+
| t |
+---------------------+
| 2012-12-13 16:42:45 |
+---------------------+
1 row in set (0.00 sec)
就跟我们上面看到的全表导出的结果一样了。
也就是说,这个问题是因为mysqldump强行设置了时区为中时区造成的。
解决1
从mysqldump的代码中我们看到,可以用 --tz-utc=0 参数去掉前面的设置时区的动作。这样用的也是默认时区。
mysqldump --tz-utc=0 -Srun/mysql.sock -uroot test tb --where='c="2012-12-14 00:42:45"' |grep INSERT
INSERT INTO `tb` VALUES ('2012-12-14 00:42:45');
可以看到,这个貌似就是我们要的结果,导出的结果也很合理。
进一步
如果这个这么好,为什么mysqldump的开发者不把—tz-utc=0作为默认行为呢?也就是说哦这样做有什么风险?
实际上是因为要防止跨时区导数据。假设你把中国一个机器上的数据导入到美国的一个mysqld(想起@plinux 说的b2b就有这种情况),若不显式地设置一个时区,在导入时就会出错了。因为都用系统默认的时区,相同的字符串值会得到不同的时间戳。如我们前面说的, 时间戳是以整型方式存储的。
解决2
所以上面的--tz-utc=0存在风险。当然如果你确定源和目标系统时区没变,是ok的。我们讨论看看有没有更保险的方法。
既然是时间戳是保险的,其实可以考虑,用时间戳来做where条件。
mysql> select unix_timestamp(c) from tb;
+-------------------+
| unix_timestamp(c) |
+-------------------+
| 1355416965 |
+-------------------+
按照表里的这个值,我们的dump命令改成
mysqldump -Srun/mysql.sock -uroot test tb --where=' unix_timestamp(c)=1355416965' | grep INSERT
INSERT INTO `tb` VALUES ('2012-12-13 16:42:45');
这次对了,而且与是否使用 --tz-utc=0 无关,都能得到结果,区别只是显示问题。
不过对MySQL比较熟悉的同学就知道,这个写法还是存在一个问题:用不上索引,因为我们在字段上做了unix_timestamp这个操作。有时候我们在这种表上为了导出方便有一个索引专门建在timestamp字段上。
因此想到用逆函数
mysqldump -Srun/mysql.sock -uroot test tb --where='c= from_unixtime(1355416965)' | grep INSERT
INSERT INTO `tb` VALUES ('2012-12-13 16:42:45');
分享到:
相关推荐
此外,MySQL允许在一个表中最多定义两个自动更新的`TIMESTAMP`字段,其中一个可以设置为`CURRENT_TIMESTAMP`作为默认值,另一个可以设置为`ON UPDATE CURRENT_TIMESTAMP`,这样在插入新行或更新行时,这两个字段都会...
例如,如果你有一个TIMESTAMP(6)的列,HOUR()函数将无法正确获取小时部分,除非你的TIMESTAMP列定义为至少TIMESTAMP(10)。 在实际应用中,选择合适的TIMESTAMP行为和显示尺寸取决于你的需求。如果需要在每次更新时...
MySQL数据库系统中,时间数据类型是用来存储日期和时间值的,其中包括`DATE`、`DATETIME`和`TIMESTAMP`。这些类型在某些方面相似,但在其他方面却有着明显的区别。下面将详细介绍`DATETIME`和`TIMESTAMP`的比较,并...
MySQL数据库提供了多种时间类型来处理日期和时间数据: 1. **DATE**:这个类型仅存储日期,格式为'YYYY-MM-DD',不包含时间部分。在Java中,对应的类型是`java.sql.Date`,它表示没有时间部分的日期。 2. **TIME**...
在MySQL 5.5版本之前,存在一个限制,即每个表中最多只能有一个`TIMESTAMP`列具有`CURRENT_TIMESTAMP`作为默认值或自动更新值。这意味着你不能在一个列中设置`DEFAULT CURRENT_TIMESTAMP`同时在另一个列中设置`ON ...
以下是一个简单的实体类示例: ```java import java.time.LocalDate; import java.time.LocalDateTime; public class Event { private Long id; private LocalDate date; private LocalDateTime dateTime; //...
这个示例提供了一个基本框架,实际应用中可能需要添加错误处理、日志记录、更复杂的定时机制(如使用`cron`或Python的`schedule`库)等。这样的自动化流程可以显著减轻运维人员的工作负担,确保数据库的定期备份,并...
在MySQL数据库中,datetime和timestamp是两种常用的日期和时间数据类型,它们虽然都可以用来存储日期和时间信息,但在使用和处理上存在一些显著的区别。本文将深入探讨这两种数据类型的差异以及如何在实际应用中选择...
2. 表中的第一个TIMESTAMP列,如果未声明NULL、DEFAULT或ON UPDATE属性,会自动获得DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP属性。这使得该列在插入新行时默认设置为当前时间,并在后续更新时自动...
在这个例子中,当我们插入一行数据并将`date1` 和 `data2` 列的值设置为`NULL`时,MySQL将自动用当前的日期和时间填充这些列。 通过以上介绍可以看出,在MySQL中,获取当前系统的日期和时间以及使用`TIMESTAMP` 列...
在mysql中timestamp数据类型是一个比较特殊的数据类型,他可以自动在你不使用程序更新情况下只要你更新了记录timestamp会自动更新时间 通常表中会有一个Create date 创建日期的字段,其它数据库均有默认值的选项。...
10. **视图**:视图是虚拟表,基于一个或多个表的查询结果。学习如何创建和使用视图,以及其在数据抽象和权限控制中的应用。 此外,手册还会涵盖MySQL的最新版本特性,如窗口函数、JSON支持和分区表等,以及如何...
在MySQL中,`TIMESTAMP`字段允许最小值'1970-01-01 00:00:01'和最大值'2038-01-19 03:14:07',但'0000-00-00 00:00:00'是作为一个特殊的无效日期值存在。当你试图插入一个非有效日期或者不指定日期时,某些情况下,...
2. **Datetime**:是一个包含了日期和时间信息的数据类型,通常用于表示具体的日期和时间点。在 Python 中,`datetime` 模块提供了 `datetime` 类来处理日期和时间对象。 #### 二、字符串日期时间转换成时间戳 在...
MySQL是一个开源、免费的关系型数据库管理系统,广泛应用于Web应用、数据分析等领域,其高效、稳定和易于维护的特点使其深受开发者喜爱。 首先,我们从基础开始,了解什么是数据库。数据库是存储和管理数据的系统,...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
首先,MySQL的UNIX_TIMESTAMP()函数是一个内置的时间和日期函数,它能够将日期或时间转换为自1970年1月1日00:00:00 GMT以来的秒数。如果函数没有参数调用,它会返回当前的Unix时间戳。如果提供了一个日期或时间参数...
mysql的日期和时间函数 这里是一个使用日期函数的例子。下面的查询选择所有 date_col 值在最后 30 天内的记录。 mysql> SELECT something FROM tbl_name WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) ...