mysql5.6 TIME,DATETIME,TIMESTAMP

http://www.cnblogs.com/justfortaste/p/4119722.html

5.6.4以后时间类型(TIME,DATETIME,TIMESTAMP)支持微秒

DATETIME范围 : ‘1000-01-01 00:00:00.000000‘ to ‘9999-12-31 23:59:59.999999‘

TIMESTAMP范围:  ‘1970-01-01 00:00:01.000000‘ to‘2038-01-19 03:14:07.999999‘

TIME 范围:         ‘-838:59:59.000000’ to ‘838:59:59.000000‘.

CREATE TABLE `b` (
  `a` char(4) DEFAULT NULL,
  `b` datetime(2) DEFAULT NULL,
  `c` char(4) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

mysql> insert into b select "aaaa",now(2),"aaaa";
Query OK, 1 row affected (0.17 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from b;
+------+------------------------+------+
| a    | b                      | c    |
+------+------------------------+------+
| aaaa | 2016-06-26 06:06:01.11 | aaaa |
+------+------------------------+------+
1 row in set (0.00 sec)
[[email protected] test]# hexdump -C b.ibd
0000bff0  00 00 00 00 00 00 00 00  2e 79 d4 a4 00 32 f0 1e  |.........y...2..|
0000c000  b7 5a db ef 00 00 00 03  ff ff ff ff ff ff ff ff  |.Z..............|
0000c010  00 00 00 00 00 32 fa 8f  45 bf 00 00 00 00 00 00  |.....2..E.......|
0000c020  00 00 00 00 00 75 00 02  00 a1 80 03 00 00 00 00  |.....u..........|
0000c030  00 80 00 05 00 00 00 01  00 00 00 00 00 00 00 00  |................|
0000c040  00 00 00 00 00 00 00 00  00 95 00 00 00 75 00 00  |.............u..|
0000c050  00 02 00 f2 00 00 00 75  00 00 00 02 00 32 01 00  |.......u.....2..|
0000c060  02 00 1d 69 6e 66 69 6d  75 6d 00 02 00 0b 00 00  |...infimum......|
0000c070  73 75 70 72 65 6d 75 6d  04 04 00 00 00 10 ff f0  |supremum........|
0000c080  00 00 00 00 0e 06 00 00  00 00 76 60 d6 00 00 01  |..........v`....|
0000c090  71 01 10 61 61 61 61 99  99 b4 61 81 0b 61 61 61  |q..aaaa...a..aaa|
0000c0a0  61 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |a...............|
0000c0b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

[2016-06-26 06:06:01.11]占用的存储空间:5+1=6
Data Type    Storage Required Before MySQL 5.6.4    Storage Required as of MySQL 5.6.4
YEAR              1 byte                  1 byte
DATE              3 bytes                  3 bytes
TIME              3 bytes                  3 bytes + fractional seconds storage
DATETIME           8 bytes                  5 bytes + fractional seconds storage
TIMESTAMP           4 bytes                  4 bytes + fractional seconds storage

微秒长度:

Fractional Seconds Precision    Storage Required
0                                       0 bytes
1, 2                                    1 byte
3, 4                                    2 bytes
5, 6                                    3 bytes

1) 5.6 支持指定小数精度

mysql> CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO fractest VALUES (‘17:51:04.777‘, ‘2014-09-08 17:51:04.777‘, ‘2014-09-08 17:51:04.777‘);
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM fractest;
+-------------+------------------------+------------------------+
| c1          | c2                     | c3                     |
+-------------+------------------------+------------------------+
| 17:51:04.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 |
+-------------+------------------------+------------------------+
1 row in set (0.00 sec)

time类型:

mysql> insert into c select "11:20";
Query OK, 1 row affected (0.17 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from c;
+----------+
| a        |
+----------+
| 11:20:00 |
+----------+
1 row in set (0.00 sec)

mysql> insert into c select "-838:59:59.000000";
Query OK, 1 row affected (0.18 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> select * from c;
+------------+
| a |
+------------+
| 11:20:00 |
| -838:59:59 |
+------------+
2 rows in set (0.00 sec)

2)5.6.4以前 插入的数据支持微秒,但插入存储的数据会忽略微秒

use test

CREATE TABLE fractest( c1 TIME, c2 DATETIME, c3 TIMESTAMP );
INSERT INTO fractest VALUES (‘17:51:04.777‘, ‘2014-09-08 17:51:04.777‘, ‘2014-09-08 17:51:04.777‘);
SELECT * FROM fractest;

+----------+---------------------+---------------------+
| c1       | c2                  | c3                  |
+----------+---------------------+---------------------+
| 17:51:04 | 2014-09-08 17:51:04 | 2014-09-08 17:51:04 |
+----------+---------------------+---------------------+

3)5.6时间函数可以指定微秒精度

mysql> select now(2);
+------------------------+
| now(2)                 |
+------------------------+
| 2016-06-26 05:35:20.57 |
+------------------------+
1 row in set (0.00 sec)
mysql>  select CURTIME(2);
+-------------+
| CURTIME(2)  |
+-------------+
| 05:39:22.91 |
+-------------+
1 row in set (0.00 sec)
mysql> select  SYSDATE(3);
+-------------------------+
| SYSDATE(3)              |
+-------------------------+
| 2016-06-26 05:40:24.591 |
+-------------------------+
1 row in set (0.00 sec)
mysql> select  UTC_TIMESTAMP(5);
+---------------------------+
| UTC_TIMESTAMP(5)          |
+---------------------------+
| 2016-06-26 12:41:06.24370 |
+---------------------------+
1 row in set (0.00 sec)

4)存储

5.6.4以前,TIME,DATETIME,TIMESTAMP 分别固定占用3,8,4字节

5.6.4以后,TIME,DATETIME,TIMESTAMP占有大小取决于微秒的精度。

TIME 3 bytes + fractional seconds storage
DATETIME 5 bytes + fractional seconds storage
TIMESTAMP 4 bytes + fractional seconds storage

而微秒的存储长度和精度的关系如下

Fractional Seconds Precision Storage Required
0 0 bytes
1, 2 1 byte
3, 4 2 bytes
5, 6 3 bytes

例如上例中的c1 TIME: 占4字节,c2 DATETIME占6字节,TIMESTAMP 占7字节,TIMESTAMP占用5字节

相关函数可以参考my_datetime_packed_to_binary

5)新老时间类型在源码中的表现

5.6 内部增加了一些新的时间类型

MYSQL_TYPE_TIMESTAMP2

MYSQL_TYPE_DATETIME2,
MYSQL_TYPE_TIME2,

用于支持微秒的存储。

而老的时间类型

MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_DATETIME,
MYSQL_TYPE_TIME

仍然保留和支持,从而兼容老的时间数据

5.6 新建的表时间字段默认使用新的类型,参考如下代码

sql/sql_yacc.yy:6514

| DATETIME type_datetime_precision
    { $$= MYSQL_TYPE_DATETIME2; }

6)binlog与新时间类型

binlog的Table_map_log_event中会记录表的元数据信息,包括库,表,列信息等。新时间类型的微秒精度信息就作为列的元数据(m_field_metadata)进行存储。类似的大字段列的列元数据存储大字段的实际长度(Field_blob::do_save_field_metadata)。

【问题重现】

1 master 上执行

use zy

CREATE TABLE t1 (id int primary key, c1 TIME, c2 DATETIME, c3 TIMESTAMP );

set sql_log_bin=0;

alter table t1 modify c3 timestamp(4);

set sql_log_bin=1;

INSERT INTO t1 VALUES (10, ‘17:51:04.98887‘, ‘2014-09-08 17:51:04.866666‘, ‘2014-09-08 17:51:04.777‘);

2 slave上执行

show slave status\G

Last_Errno: 1677

Last_Error: Column 3 of table ‘zy.t1‘ cannot be converted from type ‘timestamp‘ to type ‘timestamp‘

【分析】

1)先尝试修复,修改slave_type_conversions=‘ALL_LOSSY‘;参数slave_type_conversions可以参考 http://dev.mysql.com/doc/refman/5.5/en/replication-options-slave.html#sysvar_slave_type_conversions


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

mysql> show variables like ‘slave_type_conversions‘;                                                                                         

+------------------------+-------+

| Variable_name          | Value |

+------------------------+-------+

| slave_type_conversions |       |

+------------------------+-------+

1 row in set (0.00 sec)

mysql> set global slave_type_conversions=‘ALL_LOSSY‘;

Query OK, 0 rows affected (0.00 sec)

 

show slave status\G

  Last_Errno: 1610

  Last_Error: Could not execute Write_rows event on table zy.t1; Corrupted replication event was detected, Error_code: 1610; handler error No Error!; the event‘s master log mysql-bin.000002, end_log_pos 550

  

发现备库用备库的表结构信息解析binlog行数据(unpack_row)时出错,因此,此方法修复失败。

2)查看源码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

Rows_log_event::do_apply_event

  table_def::compatible_with

   can_convert_field_to

  ....

 

   if (field->real_type() == source_type)//本例主备类型一致

  {

    if (metadata == 0) // Metadata can only be zero if no metadata was provided  // 本例主库精度为4

    {

      /*

        If there is no metadata, we either have an old event where no

        metadata were supplied, or a type that does not require any

        metadata. In either case, conversion can be done but no

        conversion table is necessary.

       */

      DBUG_PRINT( "debug" , ("Base types are identical, but there is no metadata"));

      *order_var= 0;

      DBUG_RETURN( true );

    }

 

    DBUG_PRINT( "debug" , ("Base types are identical, doing field size comparison"));

    if (field->compatible_field_size(metadata, rli, mflags, order_var))

      DBUG_RETURN(is_conversion_ok(*order_var, rli));

    else

      DBUG_RETURN( false );

  }

   else if (metadata == 0 && //这里有对新老时间类型的兼容处理

           ((field->real_type() == MYSQL_TYPE_TIMESTAMP2 &&

             source_type == MYSQL_TYPE_TIMESTAMP) ||

            (field->real_type() == MYSQL_TYPE_TIME2 &&

             source_type == MYSQL_TYPE_TIME) ||

            (field->real_type() == MYSQL_TYPE_DATETIME2 &&

             source_type == MYSQL_TYPE_DATETIME)))

  {

    /*

      TS-TODO: conversion from FSP1>FSP2.

      Can do non-lossy conversion

      from old TIME, TIMESTAMP, DATETIME

      to new TIME(0), TIMESTAMP(0), DATETIME(0).

    */

    *order_var= -1;

    DBUG_RETURN( true);

  }

  上面代码进行类型兼容性判断,本例由于精度不一致在is_conversion_ok处会返回失败。

时间: 2024-09-28 21:57:10

mysql5.6 TIME,DATETIME,TIMESTAMP的相关文章

mysql5日期类型datetime查询范围值

1.DATE_FORMAT函数 SELECT a.create_time FROM account_log a WHERE a.create_time >= DATE_FORMAT('2014-05-10 00:00:00','%Y-%m-%d %H:%i:%s') AND a.create_time <= DATE_FORMAT('2014-05-25 23:59:59','%Y-%m-%d %H:%i:%s') 2.STR_TO_DATE函数 SELECT a.create_time FR

转 数据库中的 date datetime timestamp的区别

转 数据库中的 date datetime timestamp的区别 DATETIME, DATE和TIMESTAMP类型是相关的.本文描述他们的特征,他们是如何类似的而又不同的. DATETIME类型用在你需要同时包含日期和时间信息的值时.MySQL检索并且以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'.(“支持”意味着尽管更早的值可能工作,但不能保证他们可以.) DAT

细节决定成败-mysql中的时间存储(datetime,timestamp,int)

在mysql中存储时间,我们可以用datetime 格式,timestamp格式,也可以用int格式.那么我们设计的时候该如何考虑呢? 首先,我觉得应该明白这几个格式究竟是如何的,然后看看他们的区别,这样我们才能思考何时使用正确的格式. DATETIME格式,默认是"YYYY-MM-DD HH:MM:SS",这19个字符表示的,从1000-01-01 00:00:00-9999-12-31 23:59:59 . TIMESTAMP格式也是'YYYY-MM-DD HH:MM:SS'这样的

mysql中时间类型datetime,timestamp与int的区别

在mysql中存储时间,我们可以用datetime 格式,timestamp格式,也可以用int格式.那么我们设计的时候该如何考虑呢? 首先,我觉得应该明白这几个格式究竟是如何的,然后看看他们的区别,这样我们才能思考何时使用正确的格式. DATETIME格式,默认是"YYYY-MM-DD HH:MM:SS",这19个字符表示的,从1000-01-01 00:00:00-9999-12-31 23:59:59 . TIMESTAMP格式也是'YYYY-MM-DD HH:MM:SS'这样的

Mysql时间存储类型优缺点?DATETIME?TIMESTAMP?INT?

TIMESTAMP 4个字节储存;值以UTC格式保存;.时区转化 ,存储时对当前的时区进行转换,检索时再转换回当前的时区. DATETIME 8个字节储存;实际格式储存;与时区无关;datetime 以'YYYY- MM-DD HH:MM:SS'格式检索和显示DATETIME值.支持的范围为'1000-01-01 00:00:00'到'9999-12-31 23:59:59'TIMESTAMP值不能早于1970或晚于2037 INT 存时间戳.占用资源少,查询速度快.条件范围搜索使用betwee

timestamp 和 datetime

http://blog.csdn.net/dingxingmei/article/details/44677631 情景:在执行SQL语句的时候发现,报错:[Err] 1067 - Invalid default value for 'start_time'不合法的默认值.经过查看,start_time的格式为:timestamp,其默认值设置为"0000-00-00 00:00:00" 这个默认值是错误的.因为 timestamp的取值范围是1970-01-01 00:00:01 -

【MySQL】探究之TIMESTAMP

背景 之前有业务反馈表中start_time,end_time时间字段随着时间的推移被自动更新,这可不是业务意愿,说的严重点是要出故障的. MySQL中有DATE,DATETIME,TIMESTAMP时间类型 看看官方文档怎么说 The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. Th

解决:mysql timestamp默认值0000-00-00 00:00:00 报错

一. 问题的引出 我们在用mysql5.7创建表时,如果把timestamp(时间戳)的默认值设置为0000-00-00 00:00:00 的形式,将会产生一条报错: `RepaymentDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '回款日期', 报错信息如下: [Err] 1067 - Invalid default value for 'RepaymentDate' 二. 找出原因 这个问题和mysql中sql

mysql-5.6新特性

1. undo log undo log分离到独立的表空间,并放到单独的文件目录下:这给我们部署不同IO类型的文件位置带来便利,对于并发写入型负载,我们可以把undo文件部署到单独的高速存储设备上. 1.1. 设置 vim /etc/my.cnf [mysqld] innodb_undo_directory=/data/undolog innodb_undo_log=128 innodb_undo_tablespaces=16 1.2. 说明 innodb_undo_directory 用来指定