explicit_defaults_for_timestamp参数导致复制中断

explicit_defaults_for_timestamp是从5.6.6引入的一个新参数,默认是off。

作用:对TIMESTAMP类型列的默认值和NULL值的处理,是否启用非标准特性。

默认情况下,explicit_defaults_for_timestamp被禁用,即启用非标准特性。

什么是非标准特性?

标准特性:如果没有显示声明为 NOT NULL,则默认声明为 NULL (除timestamp外的其他数据类型)

非标准特性:如果没有显示声明为 NULL,则默认声明为 NOT NULL(timestamp)

01

当explicit_defaults_for_timestamp=0时,默认状态,即启用非标准特性

  1. TIMESTAMP列如果没有显示声明NULL属性,则会自动加上NOT NULL属性 1)如果往这个列中插入null值,会自动的设置该列的值为current timestamp值。 2)表中的第一个TIMESTAMP列,如果没有指定null属性或者没有指定默认值,也没有指定ON UPDATE语句。那么该列会自动被加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP属性。 3)第一个TIMESTAMP列之后的其他的TIMESTAMP类型的列,如果没有指定null属性,也没有指定默认值,那么该列会被自动加上DEFAULT '0000-00-00 00:00:00'属性。如果insert语句中没有为该列指定值,那么该列中插入'0000-00-00 00:00:00',并且没有warning。
  2. TIMESTAMP列如果没有显式声明NOT NULL属性(或显示声明NULL属性),那么默认的该列可以为NULL 1)此时向该列中插入null值时,会直接记录null

测试1:

id=1的行,往timestamp列插入null值时,会自动为该列设置为current time

id=2的行,插入时未指定值的timestamp列中被插入了0000-00-00 00:00:00(非表中第一个timestamp列)

id=3的行,插入时未指定值的第一个timestamp列中被插入了current time值

02

当explicit_defaults_for_timestamp=1时,即启用标准特性

  1. TIMESTAMP列如果没有显式声明NOT NULL属性(或显示声明NULL属性),那么默认的该列可以为null 1)此时向该列中插入null值时,会直接记录null,而不是current timestamp值。
  2. TIMESTAMP列如果显示声明NOT NULL属性 1)没有指定默认值,此时如果向表中插入记录,但是没有给该TIMESTAMP列指定值的时候,如果strict sql_mode被指定了,那么会直接报错。如果strict sql_mode没有被指定,那么会向该列中插入'0000-00-00 00:00:00'并且产生一个warning 2)指定了默认值,除DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP外,默认值会变成'0000-00-00 00:00:00'

测试2:

id=1的行,如果timestamp列指定not null属性,在非stric sql_mode模式下,如果插入的时候该列没有指定值,那么会向该列中插入0000-00-00 00:00:00,并且产生告警

通过对 explicit_defaults_for_timestamp的了解,排查一个问题

架构如下:

现象:

二级从库复制频繁中断,一级从库正常

日志:

2017-08-18 14:17:47 357305 [ERROR] Slave SQL: Error 'Column 'modified' cannot be null' on query. Default database: 'jpos'. Query: 'insert into activity_account_sum(id,activity_id,income_number,expend_number,created,modified) values(0,584126,0,0,'2017-08-18 14:17:46',null)', Error_code: 1048
2017-08-18 14:17:47 357305 [Warning] Slave: Column 'modified' cannot be null Error_code: 1048
2017-08-18 14:17:47 357305 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.000233' position 879369308

初步分析:

通过日志信息可知,modified字段插入了null值,与表声明的not null冲突,导致错误引起复制中断。

具体分析:

  • mysql主库为5.5.38版本,一、二级从库版本为5.6.36,我们知道5.6后引入explicit_defaults_for_timestamp参数,通过查看explicit_defaults_for_timestamp=on,也就是timestamp采用的是标准特性,modified字段指定了NOT NULL并且有DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP默认值。
  • 查看表结构:
  • 查看sql mode:都没有启用stric严格模式
  • 通过以上信息可知,modified列插入null值会报错:ERROR 1048 (23000): Column 'modified' cannot be null。但是为什么一级从库没有报错呢?二级从库已获取到binlog,说明一级从库已执行完成。主库是5.5.38,比从库版本低,推断可能是出于版本兼容性考虑,在解析SQL时保持与5.5.38一致的策略,所以一级从库执行成功;二级从库与一级从库版本一致,直接使用5.6.36解析SQL的策略,所以二级从库执行失败。

解决:

  1. 修改二级从库explicit_defaults_for_timestamp=0,往timestamp数据类型列插入null值时,会自动为该列设置为current time(需要重启mysql服务后恢复)
  2. 研发修改sql,将null值修改成now()

explicit_defaults_for_timestamp跟其他参数正好相反,NULL或NOT NULL需要十分注意,最好的方式就是规范话,统一为NOT NULL 再加上默认值,即便如此,跨版本之间也容易出现问题,所以新版本上线前新引入的参数一定要有所了解,不然一不小心就会入坑。

原文发布于微信公众号 - MYSQL轻松学(learnmysql)

原文发表时间:2017-09-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏个人分享

SparkSQL相关语句总结

1.in 不支持子查询 eg. select * from src where key in(select key from test); 支持查询个...

672
来自专栏Ryan Miao

mysql插入日期 vs oracle插入日期

今天做oracle日期插入的时候突然开始疑惑日期是如何插入的。 用框架久了,反而不自己做简单的工作了。比如插入。 通常,新建一个表对象,然后绑定数据,前端for...

2829
来自专栏xingoo, 一个梦想做发明家的程序员

Elasticsearch——分页查询From&Size VS scroll

Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回。那么,如果要实现分页查询该怎么办呢? 更多内容参考Ela...

5096
来自专栏数据库

干货!超过500行的Mysql学习笔记

本文为作者初学Mysql时做的笔记,囊括了Mysql相关基本知识,内容较多超过500行笔记,希望对大家有帮助。 ? /* 启动MySQL */ net star...

1916
来自专栏PPV课数据科学社区

SQL Server优化50法

查询速度慢的原因很多,常见如下几种: 1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2、I/O吞吐量小,形成了瓶颈效...

3177
来自专栏机器学习算法与Python学习

SQL Server常用命令(平时不用别忘了)

SQL Server 2008 在Microsoft的数据平台上发布,可以组织管理任何数据。可以将结构化、半结构化和非结构化文档的数据直接存储到数据库中。可以对...

2777
来自专栏Java3y

Oracle总结【SQL细节、多表查询、分组查询、分页】

前言 在之前已经大概了解过Mysql数据库和学过相关的Oracle知识点,但是太久没用过Oracle了,就基本忘了…印象中就只有基本的SQL语句和相关一些概念…...

34810
来自专栏伦少的博客

hive查询报错:java.io.IOException:org.apache.parquet.io.ParquetDecodingException

转载请务必注明原创地址为:https://dongkelun.com/2018/05/20/hiveQueryException/

32017
来自专栏轮子工厂

深入理解MySQL---数据库知识最全整理,这些你都知道了吗?

对于后端开发人员来说,经常会和数据打交道,今天总结下数据库相关的知识。包括MySQL,JDBC基础,JDBC进阶,MongoDB,性能优化等知识点。

823
来自专栏杨建荣的学习笔记

数据紧急修复之启用错误日志 (r2第12天)

昨晚对测试环境进行了升级,同步了部分生产的数据。整个过程比较顺利,但是在最后一步启用foreign key constraint的时候报了错误。 ora-022...

2629

扫码关注云+社区