mysql text not null_【20181101】MySQL text类型的column设置为NOT NULL 导致主从1364

环境

系统版本 : CentOS release 6.8 (Final)

MySQL版本:5.6.29-log MySQL Community Server (GPL)

MySQL主从配置信息

binlog format :MIXED

sql_mode: NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

问题描述

从库show slave status监控的时候发现sql_thread进程已经变成NO,并且爆出了1362错误,仔细查看报错的是一条insert into语句,并且抛出了一个详细的错误,大致的意思就是字段column_1设置了NOT NULL但是没有插入值并且没有默认值。然后仔细检查了一下表结构,具体信息如下

字段column_1的确设置的是NOT NULL并且没有设置default 默认值。

column_1字段是是text类型,所以是无法设置defaut默认值。

本地环境手动执行验证

在看到这个报错的信息的时候,直接google了一下,大部分答案显示都是由于sql_mode的原因所导致的,要想解决这个问题,必须将执行:

mysql> set global sql_mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";

但是我在slave获取得到的sql_mode就是 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,这个时候我在自己本地执行这个insert 插入语句验证是否可以插入成功,发现是可以插入的。

猜想

这个时候我就想这个是否在主从复制的过程中,slave在执行这个insert插入的时候sql_mode发生了更改了,这个时候我解析slave的relay log信息获取得到 :

# at 271

#181019 12:13:00 server id 5403005 end_log_pos 319 CRC32 0x755a7204 GTID [commit=yes]

SET @@SESSION.GTID_NEXT= '8e91de47-8f0b-11e8-824c-246e9699bb48:1408667354'/*!*/;

# at 319

#181019 12:13:00 server id 5403005 end_log_pos 440 CRC32 0x1add7880 Query thread_id=47560669 exec_time=0 error_code=0

SET TIMESTAMP=1539922380/*!*/;

SET @@session.pseudo_thread_id=47560669/*!*/;

SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;

SET @@session.sql_mode=1344274432/*!*/;

SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;

/*!\C utf8mb4 *//*!*/;

SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=45/*!*/;

SET @@session.time_zone='SYSTEM'/*!*/;

SET @@session.lc_time_names=0/*!*/;

SET @@session.collation_database=DEFAULT/*!*/;

BEGIN

/*!*/;

# at 440

#181019 12:13:00 server id 5403005 end_log_pos 689 CRC32 0x1537384f Query thread_id=47560669 exec_time=0 error_code=0

use `finance_fixin_product`/*!*/;

SET TIMESTAMP=1539922380/*!*/;

.....

.....

.....

/*!*/;

可以很明显的得到在上面binlog中有一个 SET @@session.sql_mode=1344274432/!/; 操作,那么这操作将赋予sql_mode什么值呢?

mysql> SET @@session.sql_mode=1344274432;

Query OK, 0 rows affected (0.00 sec)

mysql> select @@global.sql_mode;

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

| @@global.sql_mode |

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

| NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |

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

1 row in set (0.00 sec)

mysql> select @@sql_mode;

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

| @@sql_mode |

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

| STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |

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

1 row in set (0.00 sec)

执行操作之后,突然发现sql_mode多出来一个STRICT_TRANS_TABLES,这个时候大致可以获取得到端倪了,因为在binlog在执行这条SQL的设置了session的sql_mode为严格模式,所以导致在sql_thread重放的时候出现了这个问题。

但是这个时候又冒出了一个新的问题,因为线上的表结构和架构和测试环境一模一样,并且线上运行了这么久的时间也没有出现这个问题,带着这个疑问我再次解析了线上binlog的日志信息:

#181101 10:12:26 server id 5403005 end_log_pos 420 CRC32 0x2fe38b78 Query thread_id=51519927 exec_time=0 error_code=0

SET TIMESTAMP=1541038346/*!*/;

SET @@session.pseudo_thread_id=51519927/*!*/;

SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;

SET @@session.sql_mode=1344274432/*!*/;

SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;

/*!\C utf8mb4 *//*!*/;

SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=45/*!*/;

SET @@session.time_zone='SYSTEM'/*!*/;

SET @@session.lc_time_names=0/*!*/;

SET @@session.collation_database=DEFAULT/*!*/;

BEGIN

/*!*/;

# at 420

#181101 10:12:26 server id 5403005 end_log_pos 538 CRC32 0xb848f658 Table_map: `finance_fixin_cgb_gateway`.`t_cgb_receive_message` mapped to number 2056756

# at 538

#181101 10:12:26 server id 5403005 end_log_pos 740 CRC32 0x42756468 Write_rows: table id 2056756 flags: STMT_END_F

### INSERT INTO

### SET

### @1=5300431

### @2='PA0052'

### @3='b0009201811010033433728'

### @4='10.201.5.129'

### @5=2433

### @6='128'

### @7='0009a201811010143659612590571520'

### @8='000920180907OR23805082566791168'

### @9='0'

### @10='0000'

### @11='0000-操作成功。'

### @12='2018-11-01 10:12:26'

### @13='2018-11-01 10:12:26'

# at 740

#181101 10:12:26 server id 5403005 end_log_pos 771 CRC32 0xf5516de4 Xid = 12837058229

COMMIT/*!*/;

对比之后发现,线上的binlog格式是ROW格式,并且通过查看insert语句发现在insert插入的时候没有默认值会默认设置为' ',所以slave是不会报错的。

解决问题

这个时候提出了俩个方案:

更改表结构,允许为NULL

设置master的binlog为ROW格式

最后和开发沟通之后还是选择了第一个方案,修改表结构,主要是binlog格式的修改,必须先要断开所有的链接,所以综合考虑直接修改了表结构。

补充:

在binlog为statement的时候解析了发现了一条SET TIMESTAMP=1539922380语句,之前一直认为在statement格式下面使用时间函数会导致主从数据不一致,现在看到这个SQL,发现并不出现这种情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值