【背景】

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

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

TIMESTAMP范围: values is '1970-01-01 00:00:01.000000' to'2038-01-19 03:14:07.999999'

1) 5.6 支持指定小数精度

use test

CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
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.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 |
+-------------+------------------------+------------------------+

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时间函数(CURTIME()SYSDATE(), or UTC_TIMESTAMP())可以指定微秒精度

mysql> select CURTIME(2);
+-------------+
| CURTIME(2)  |
+-------------+
| 11:26:56.43 |
+-------------+

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

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)查看源码:

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处会返回失败。

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

  1. MySQL5日期类型DATETIME和TIMESTAMP相关问题详解

    MySQL5日期类型DATETIME和TIMESTAMP相关问题详解 MySQL5的日期类型有三种:DATETIME.DATE和TIMESTAMP,除了DATE用来表示一个不带时分秒的是日期,另外两个 ...

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

    转 数据库中的 date datetime timestamp的区别 DATETIME, DATE和TIMESTAMP类型是相关的.本文描述他们的特征,他们是如何类似的而又不同的. DATETIME类 ...

  3. Mysql 实战关于date,datetime,timestamp类型使用

    最近在做一个项目 项目中 不同的小伙伴同时在不同的业务模块中用到了date,datetime,timestamp这三个类型 特别是datetime,timestamp这两个 如果不能理解到位  其实很 ...

  4. mysql的日期存储字段比较int,datetime,timestamp区别

    1.首先是我们分析datetime长度是8个字节,INT的长度是4个字节,存储空间上比datatime少. 2.int存储索引的空间也比datetime少,排序效率高,查询速度比较快. 3.方便计算, ...

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

    在mysql中存储时间,我们可以用datetime 格式,timestamp格式,也可以用int格式.那么我们设计的时候该如何考虑呢? 首先,我觉得应该明白这几个格式究竟是如何的,然后看看他们的区别, ...

  6. mysql5.7 版本中 timestamp 不能为零日期 以及sql_mode合理设置

    ---恢复内容开始--- 摘要: mysql5.7版本相比较之前的版本有很多的特性的增加以及默认配置的改变,在使用中难免会遇到与之前的使用习惯或者项目需求不符的情况.就需要调整相应的变量的值,比如sq ...

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

    TIMESTAMP 4个字节储存;值以UTC格式保存;.时区转化 ,存储时对当前的时区进行转换,检索时再转换回当前的时区. DATETIME 8个字节储存;实际格式储存;与时区无关;datetime  ...

  8. MySQL中Date,DateTime,TimeStamp和Time的比较

    名称 显示格式 显示范围 应用场景 后台取值 Date YYYY-MM-DD 1601-01-01 到 9999-01-01 当业务需求中只需要精确到天时, 可以用这个时间格式 @JSONField( ...

  9. Mysql中date,time,datetime,timestamp的区别

    区别: timestamp:时间戳.北京时间1970年01月01日08时00分00秒 起至现在的总秒数. datetime:带时分秒的完整时间,例如:1970-01-01 10:00:00 date: ...

随机推荐

  1. NHibernate系列文章二:创建NHibernate工程

    摘要 这篇文章介绍了如何创建一个简单的使用NHibernate的控制台应用程序,包括使用NuGet.简单的配置.单表映射.对NHibernate配置文件添加智能提示.使用ISessionFactory ...

  2. Shell_参数替换(転)

    From: http://www.cnblogs.com/yjf512/archive/2013/06/03/3114803.html Bash中的$符号的作用是参数替换,将参数名替换为参数所代表的值 ...

  3. 解析工具Goson

    /** * 解析申请分配座位席别 * @param json * @return */ public static TrainOrderResponse getTrainOrder(String js ...

  4. noip2006 2^k进制数

    设r是个2k进制数,并满足以下条件: (1)r至少是个2位的2k进制数. (2)作为2k进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后,则q的总位数不超过w ...

  5. CSS详细样式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  6. 【MVC】 非常简单的页面导出 WORD, EXCEL方法

    [MVC] 页面导出 WORD, EXCEL 前端 js function output() { var para = new Object(); para.html = getHtml(" ...

  7. Selenium2+python自动化21-TXT数据参数化

    前言      在17篇我们讲了excel数据的参数化,有人问了txt数据的参数化该怎么办呢,下面小编为你带你txt数据参数化的讲解 一.以百度搜索为例,自动搜索五次不同的关键字.输入的数据不同从而引 ...

  8. Python环境下NIPIR(ICTCLAS2014)中文分词系统使用攻略

    一.安装 官方链接:http://pynlpir.readthedocs.org/en/latest/installation.html 官方网页中介绍了几种安装方法,大家根据个人需要,自行参考!我采 ...

  9. (转)Quartus II和Modelsim的联合仿真(详细)

    这篇文章不需要在modelsim中建库.映射.建工程等一些繁琐的步骤,直接使用modelsim中的默认work库.使用quartus+modelsim联合仿真. 首先推荐一篇文章 http://www ...

  10. JS 获取服务器时间

    function getSevertime(){ var xmlHttp = new XMLHttpRequest(); xmlHttp.open("get",location.h ...