故障解析丨导入字符串NULL导致主从报错

news2024/12/23 13:43:35

1.背景概述

目前需要搭建一个从库,由于单表数据量较大,时间比较有限,考虑到导入导出的时间,并且GreatSQL支持并行load data的功能,能够加速数据的导入,因此决定使用 select into outfile 和 load data 的方式进行数据的迁移;

在数据导入完成后进行数据同步,从库发生报错 1032 找不到记录,但是登录从库中可以查询到此条记录,这里就很奇怪;

最后通过解析relaylog,根据relaylog中的update记录,以每个字段为查询条件进行查询,发现是由于NULL值列导致的,主库这列的值是 NULL,从库在导入后导成了字符串"NULL",因此导致回放update操作时匹配不到数据而报错1032.

2.问题复现

本次测试基于 GreatSQL 8.0.32-24

2.1 初始化2个单机实例

2.2 主节点创建测试表

greatsql> create database test;
greatsql> use test;

greatsql> create table t1 (id int,
name varchar(30),
age int,
addr varchar(30),
school varchar(30),
unique key (id)) engine=innodb;

greatsql> insert into t1 values
(1,'小红',10,'北京','一中'),
(2,'小绿',11,'北京','一中'),
(3,'小黄',12,'北京',NULL),
(4,'小蓝',13,'北京',NULL),
(5,'小黑',14,'北京',NULL);

2.3 查看数据

greatsql> select * from t1;
+----+--------+------+--------+--------+
| id | name  | age  | addr  | school |
+----+--------+------+--------+--------+
|  1 | 小红  |  10 | 北京  | 一中  |
|  2 | 小绿  |  11 | 北京  | 一中  |
|  3 | 小黄  |  12 | 北京  | NULL  |
|  4 | 小蓝  |  13 | 北京  | NULL  |
|  5 | 小黑  |  14 | 北京  | NULL  |
+----+--------+------+--------+--------+
5 rows in set (0.00 sec)

2.4 主节点导出数据

greatsql> select * from test.t1 into outfile '/greatsql/t1.csv' FIELDS TERMINATED BY '|+|'  ESCAPED BY '' LINES TERMINATED BY '/*rowsxxx*/';

2.5 查看导出的数据

$ cat t1.csv 

1|+|小红|+|10|+|北京|+|一中/*rowsxxx*/2|+|小绿|+|11|+|北京|+|一中/*rowsxxx*/3|+|小黄|+|12|+|北京|+|NULL/*rowsxxx*/4|+|小蓝|+|13|+|北京|+|NULL/*rowsxxx*/5|+|小黑|+|14|+|北京|+|NULL/*rowsxxx

可以看到导出的数据中包含 NULL

2.6 从库创建表并导入数据

greatsql> create database test;
use test;
create table t1 (id int,
name varchar(30),
age int,
addr varchar(30),
school varchar(30),
unique key (id)) engine=innodb;

导入数据

greatsql> load data  infile '/greatsql/t1.csv' into table test.t1 fields terminated by '|+|' ESCAPED BY '' lines terminated by '/*rowsxxx*/'; 

2.7 从库查询数据

greatsql> select * from test.t1;
+----+--------+------+--------+--------+
| id | name  | age  | addr  | school |
+----+--------+------+--------+--------+
|  1 | 小红  |  10 | 北京  | 一中  |
|  2 | 小绿  |  11 | 北京  | 一中  |
|  3 | 小黄  |  12 | 北京  | NULL  |
|  4 | 小蓝  |  13 | 北京  | NULL  |
|  5 | 小黑  |  14 | 北京  | NULL  |
+----+--------+------+--------+--------+
5 rows in set (0.00 sec)

2.8 从库建立复制

greatsql> reset master;
Query OK, 0 rows affected (0.04 sec)

greatsql> set global gtid_purged='b94e6517-68dd-11ee-b43b-00163ecb92e3:1-5755';
Query OK, 0 rows affected (0.00 sec)

greatsql> show master status;
+---------------+----------+--------------+------------------+---------------------------------------------+
| File      | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set              |
+---------------+----------+--------------+------------------+---------------------------------------------+
| binlog.000001 |    153 |        |          | b94e6517-68dd-11ee-b43b-00163ecb92e3:1-5755 |
+---------------+----------+--------------+------------------+---------------------------------------------+
1 row in set (0.00 sec)

greatsql> change master to master_user='root',master_password='greatdb',master_host='192.168.137.162',master_port=6001,master_auto_position=1;
Query OK, 0 rows affected, 7 warnings (0.02 sec)

greatsql> start slave;
Query OK, 0 rows affected, 1 warning (0.04 sec)

greatsql> show slave status\G
*************************** 1. row ***************************
        Slave_IO_State: Waiting for source to send event
         Master_Host: 192.168.137.162
         Master_User: root
         Master_Port: 6001
        Connect_Retry: 60
       Master_Log_File: binlog.000002
     Read_Master_Log_Pos: 1861574
        Relay_Log_File: relaylog.000002
        Relay_Log_Pos: 395
    Relay_Master_Log_File: binlog.000002
       Slave_IO_Running: Yes
      Slave_SQL_Running: Yes
       Replicate_Do_DB: 
......

2.9 主库更新数据

greatsql> update test.t1 set name='小小黑' where id=5;

2.10 从库查看复制状态

greatsql> show slave status\G
*************************** 1. row ***************************
        Slave_IO_State: Waiting for source to send event
         Master_Host: 172.17.137.162
         Master_User: root
         Master_Port: 6001
        Connect_Retry: 60
       Master_Log_File: binlog.000002
     Read_Master_Log_Pos: 1863564
        Relay_Log_File: relaylog.000002
        Relay_Log_Pos: 395
    Relay_Master_Log_File: binlog.000002
       Slave_IO_Running: Yes
      Slave_SQL_Running: No
       Replicate_Do_DB: 
     Replicate_Ignore_DB: 
      Replicate_Do_Table: 
    Replicate_Ignore_Table: 
   Replicate_Wild_Do_Table: 
 Replicate_Wild_Ignore_Table: 
          Last_Errno: 1032
          Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'b94e6517-68dd-11ee-b43b-00163ecb92e3:5756' at master log binlog.000002, end_log_pos 1863537. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
         Skip_Counter: 0
......

greatsql> select * from performance_schema.replication_applier_status_by_worker limit 1\G
*************************** 1. row ***************************
                      CHANNEL_NAME: 
                       WORKER_ID: 1
                       THREAD_ID: NULL
                     SERVICE_STATE: OFF
                   LAST_ERROR_NUMBER: 1032
                   LAST_ERROR_MESSAGE: Worker 1 failed executing transaction 'b94e6517-68dd-11ee-b43b-00163ecb92e3:5756' at master log binlog.000002, end_log_pos 1863537; Could not execute Update_rows event on table test.t1; Can't find record in 't1', Error_code: 1032; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log FIRST, end_log_pos 1863537
                  LAST_ERROR_TIMESTAMP: 2023-10-17 10:02:46.396166
                LAST_APPLIED_TRANSACTION: 
   LAST_APPLIED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP: 0000-00-00 00:00:00.000000
  LAST_APPLIED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP: 0000-00-00 00:00:00.000000
     LAST_APPLIED_TRANSACTION_START_APPLY_TIMESTAMP: 0000-00-00 00:00:00.000000
      LAST_APPLIED_TRANSACTION_END_APPLY_TIMESTAMP: 0000-00-00 00:00:00.000000
                  APPLYING_TRANSACTION: b94e6517-68dd-11ee-b43b-00163ecb92e3:5756
     APPLYING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP: 2023-10-17 10:02:46.392331
    APPLYING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP: 2023-10-17 10:02:46.392331
       APPLYING_TRANSACTION_START_APPLY_TIMESTAMP: 2023-10-17 10:02:46.393814
         LAST_APPLIED_TRANSACTION_RETRIES_COUNT: 0
  LAST_APPLIED_TRANSACTION_LAST_TRANSIENT_ERROR_NUMBER: 0
 LAST_APPLIED_TRANSACTION_LAST_TRANSIENT_ERROR_MESSAGE: 
LAST_APPLIED_TRANSACTION_LAST_TRANSIENT_ERROR_TIMESTAMP: 0000-00-00 00:00:00.000000
           APPLYING_TRANSACTION_RETRIES_COUNT: 0
    APPLYING_TRANSACTION_LAST_TRANSIENT_ERROR_NUMBER: 0
   APPLYING_TRANSACTION_LAST_TRANSIENT_ERROR_MESSAGE: 
  APPLYING_TRANSACTION_LAST_TRANSIENT_ERROR_TIMESTAMP: 0000-00-00 00:00:00.000000
1 row in set (0.00 sec)

可以看到从库发生1032报错,找不到记录

2.11 解析从库relay log

#231017 10:02:46 server id 1  end_log_pos 1863456 Table_map: `test`.`t1` mapped to number 180
\# has_generated_invisible_primary_key=0
\# at 673
\#231017 10:02:46 server id 1  end_log_pos 1863537 Update_rows: table id 180 flags: STMT_END_F
\### UPDATE `test`.`t1`
\### WHERE
\###  @1=5 /* INT meta=0 nullable=1 is_null=0 */
\###  @2='小黑' /* VARSTRING(120) meta=120 nullable=1 is_null=0 */
\###  @3=14 /* INT meta=0 nullable=1 is_null=0 */
\###  @4='北京' /* VARSTRING(120) meta=120 nullable=1 is_null=0 */
\###  @5=NULL /* VARSTRING(120) meta=120 nullable=1 is_null=1 */
\### SET
\###  @1=5 /* INT meta=0 nullable=1 is_null=0 */
\###  @2='小小黑' /* VARSTRING(120) meta=120 nullable=1 is_null=0 */
\###  @3=14 /* INT meta=0 nullable=1 is_null=0 */
\###  @4='北京' /* VARSTRING(120) meta=120 nullable=1 is_null=0 */
\###  @5=NULL /* VARSTRING(120) meta=120 nullable=1 is_null=1 */
\# at 754
\#231017 10:02:46 server id 1  end_log_pos 1863564 Xid = 5940
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by greatsqlbinlog */ /*!*/;
DELIMITER ;
\# End of log file

img

可以看到update更新前的数据与从库的数据一致,那么为什么还会报错 找不到记录呢?

2.12 根据relay log中的内容去从库查询数据

greatsql> select * from test.t1 where id=5;
+------+--------+------+--------+--------+
| id  | name  | age  | addr  | school |
+------+--------+------+--------+--------+
|   5 | 小黑  |  14 | 北京  | NULL  |
+------+--------+------+--------+--------+
1 row in set (0.01 sec)

greatsql> select * from test.t1 where name='小黑';
+------+--------+------+--------+--------+
| id  | name  | age  | addr  | school |
+------+--------+------+--------+--------+
|   5 | 小黑  |  14 | 北京  | NULL  |
+------+--------+------+--------+--------+
1 row in set (0.01 sec)

greatsql> select * from test.t1 where age=14;
+------+--------+------+--------+--------+
| id  | name  | age  | addr  | school |
+------+--------+------+--------+--------+
|   5 | 小黑  |  14 | 北京  | NULL  |
+------+--------+------+--------+--------+
1 row in set (0.00 sec)

greatsql> select * from test.t1 where addr='北京';
+------+--------+------+--------+--------+
| id  | name  | age  | addr  | school |
+------+--------+------+--------+--------+
|   1 | 小红  |  10 | 北京  | 一中  |
|   2 | 小绿  |  11 | 北京  | 一中  |
|   3 | 小黄  |  12 | 北京  | NULL  |
|   4 | 小蓝  |  13 | 北京  | NULL  |
|   5 | 小黑  |  14 | 北京  | NULL  |
+------+--------+------+--------+--------+
5 rows in set (0.00 sec)

greatsql> select * from test.t1 where school is null;
Empty set (0.01 sec)

greatsql> select * from test.t1 where school='null';
+------+--------+------+--------+--------+
| id  | name  | age  | addr  | school |
+------+--------+------+--------+--------+
|   3 | 小黄  |  12 | 北京  | NULL  |
|   4 | 小蓝  |  13 | 北京  | NULL  |
|   5 | 小黑  |  14 | 北京  | NULL  |
+------+--------+------+--------+--------+
3 rows in set (0.00 sec)

可以看到,根据null值作为查询条件时,匹配不到数据; 根据字符串"null" 进行匹配是可以匹配到数据

2.13 去主库进行查询

greatsql> select * from test.t1 where school is null;
+------+-----------+------+--------+--------+
| id  | name    | age  | addr  | school |
+------+-----------+------+--------+--------+
|   3 | 小黄    |  12 | 北京  | NULL  |
|   4 | 小蓝    |  13 | 北京  | NULL  |
|   5 | 小小黑   |  14 | 北京  | NULL  |
+------+-----------+------+--------+--------+
3 rows in set (0.00 sec)

greatsql> select * from test.t1 where school='null';
Empty set (0.00 sec)

在主库查询的结果与从库相反

可以得出结论,由于从库导入的数据将NULL值列的数据导入成了字符串 NULL,因此导致主从数据出现了不一致。

2.14 修复从库

greatsql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

greatsql> update test.t1 set school=NULL where school='null';
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3  Changed: 3  Warnings: 0

greatsql> start slave;
Query OK, 0 rows affected, 1 warning (0.04 sec)

greatsql> show slave status\G
*************************** 1. row ***************************
        Slave_IO_State: Waiting for source to send event
         Master_Host: 172.17.137.162
         Master_User: root
         Master_Port: 6001
        Connect_Retry: 60
       Master_Log_File: binlog.000002
     Read_Master_Log_Pos: 1863564
        Relay_Log_File: relaylog.000003
        Relay_Log_Pos: 435
    Relay_Master_Log_File: binlog.000002
       Slave_IO_Running: Yes
      Slave_SQL_Running: Yes
       Replicate_Do_DB: 
......

可以看到主从状态已经恢复正常

3.总结

1.如果FIELDS ESCAPED BY字符为空字符,则没有字符被转义,并且NULL被作为NULL输出,而不是\N;这也是导致此次主从报错的原因。

2.如果这张表使用的是主键而不是唯一索引,即使某些列被导入为字符串NULL,也不会报错。

3.如果这张表没有索引或有普通索引,则会报错。

Enjoy GreatSQL :)


关于GreatSQL

GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。

相关链接

GreatSQL社区

Gitee

Github

Bilibili

技术交流群

微信:添加GreatSQL社区助手好友,微信号wanlidbc发送验证信息加群

QQ群:533341697

Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

技术交流群:

微信&QQ群:

QQ群:533341697

微信群:添加GreatSQL社区助手(微信号:wanlidbc )好友,待社区助手拉您进群。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1306600.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式(三)-结构型模式(1)-适配器模式

一、为何需要适配器模式(Adapter)? 在软件设计中,某个模块里有很多公用的功能接口,其中有些公用接口需要用到不同的类当中时,会出现接口不兼容的问题。因为这些不同的类对这个相同任务的接口,都有各自代码…

全栈必备——网络编程基础

我们是幸运的,因为我们拥有网络。网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界。 然而,网络的无标度和小世界特性使得它又是复杂的,无所不在,无所不能,以致于我们无法区分甚至…

镭速助力集成绘图建模工具加速文件传输速度

在当前信息化社会中,绘图建模工具已经成为许多人不可或缺的伙伴。无论是学习、工作还是生活,这些工具都能够在表达思想、设计方案以及展示成果等方面发挥重要作用。然而,随着绘图建模工具功能的日益强大,用户创作的文件也变得越来…

基于ssm大学生创新创业平台项目管理子系统设计与实现论文

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对大学生创新创业项目信息管理混乱,出错率高,信…

js基础:简介、变量与数据类型、流程循环控制语句、数组及其api

JS基础:简介、变量与数据类型、流程循环控制语句、数组及其api 一、简介 1、js概述 tip:JavaScript是什么? 有什么作用? JavaScript(简称JS)是一种轻量级的、解释性的编程语言,主要用于在网页…

java系列-LinkedHashMap怎么实现LRU

1.定义变量accessOrder public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {final boolean accessOrder;public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor…

小间距LED显示屏的芯片扮演的关键角色

LED屏幕由数万颗灯珠封装而成&#xff0c;包含驱动芯片、PCB板、电阻、电容、模组套件和箱体等&#xff0c;形成一块高清LED显示屏。芯片的质量直接影响整个屏幕的品质、稳定性和性能。那么&#xff0c;什么是细间距LED显示屏&#xff1f;小间距LED显示屏芯片具体有何作用呢&am…

设计模式(2)--对象创建(1)--抽象工厂

1. 意图 提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 2. 四种角色 抽象产品(Product)、具体产品(Concrete Product)、抽象工厂(Abstract Factory)、具体工厂(Concrete Factory)。 3. 优点 3.1 分离了具体的类。Client只需使用抽象工厂类…

易生支付与青岛国资之间的合作即将成为现实。青岛国资决定以曲线入股易生支付。

易生金服的次要股权可能会有新的控制方。 根据西米支付网的消息&#xff0c;经营支付服务的持牌机构“易生支付”的唯一股东“易生金服”的第二大股东凯撒同盛发展股份有限公司的控股权将转让给青岛环海湾文化旅游发展有限公司&#xff0c;同时实际控制权也将交由青岛市市北区国…

java ATM swing窗体转账,取款,存款等

ATM 转账&#xff0c;取款&#xff0c;存款等等 开发环境 开发语言为Java&#xff0c;开发环境Eclipse或者IDEA都可以。 系统框架 利用JDK自带的 框架开发&#xff0c; 纯窗体模式&#xff0c;直接运行Main文件即可以。 涉及主要技术 银行ATM系统 系统用Java语言编写&a…

抖店做起来到底有多难?带你揭露抖音电商的真相!

我是电商珠珠 无论是谁问抖店还能做吗&#xff1f;基本上答案都是肯定的。他们只会说做店很简单&#xff0c;而不会告诉你做电商的压力&#xff0c;以及最真实的投资。 做抖店的风险他们都是一笔带过&#xff0c;好像无论是谁都能做一样。大部分电商公司都会让你做无货源&…

火力发电厂防雷及浪涌防护解决方案

火力发电厂是一种利用燃料燃烧产生的热能驱动汽轮机发电的设施&#xff0c;是目前世界上最常见的发电方式之一。火力发电厂的运行需要大量的电气设备&#xff0c;如辅机马达、通信系统、MIS系统、DCS系统等&#xff0c;这些设备对雷电分敏感&#xff0c;特别是DCS系统&#xff…

如何实现nacos的配置的热更新

我们在使用nacos进行修改配置后&#xff0c;需要微服务无需重启即可让配置生效&#xff0c;也就是使配置进行热更新我们可以采用下面的两种方式进行配置的热更新操作 方式一&#xff1a;在Value所注入的变量的类上添加注解RefreshScope RestController RequestMapping("/o…

Kubernetes(k8s)集群部署----->超详细

Kubernetes&#xff08;k8s&#xff09;集群部署-----&#xff1e;超详细 一、资源准备二、安装准备2.1 主机环境设置2.1.1 关闭操作系统防火墙、selinux2.1.2 关闭swap交换分区2.1.3 允许iptables检测桥接流量&#xff08;可选&#xff09; 2.2 安装Docker环境2.3 安装Kubeadm…

34、卷积实战 - 手写一个基础卷积算法

前面基本上把卷积这一算法的原理和公式介绍完了,如果还有不懂的,可以多翻几遍前面的章节内容,深入理解一下。 本节加一个实战,大家可以手动来实现一个卷积算法,本文中以 python 代码为例,C++ 的代码可以查看本节后面的链接。 说到卷积实现,其实就是自己手写一个卷积算…

pycharm中py文件设置参数

在py文件中右键 直接对应复制进去即可

python matplotlib set_aspect

说明: # 设置轴比例相等&#xff0c;以获得圆柱体视角 ax.set_aspect(equal) 代码案例: import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np# 创建数据 theta np.linspace(0, 2*np.pi, 100) z np.linspace(0, 1, 100) r z**2 …

Llama2-Chinese-7b-Chat安装部署

文章目录 前言一、文件介绍 &#x1f4c1;二、环境配置 ♟三、Llama2-Chinese-7b-Chat下载 ⏬总结 前言 本文主要介绍如何使用Llama2-Chinese-7b-Chat&#xff0c;最后的效果如图所示&#xff1a; 一、文件介绍 &#x1f4c1; ⬇️ 下载地址&#xff1a;https://pan.baidu.…

Facebook运营技巧详解,Facebook多店铺如何运营?

在前不久的文章中就讲过Facebook养号和广告的投放技巧&#xff0c;今天东哥就趁热打铁来接着讲讲Facebook的运营技巧&#xff0c;现在做外贸和跨境电商的人基本上都用过Facebook&#xff0c;像在流量这么庞大的平台上想要抓住更多机遇&#xff0c;懂得一些运营技巧是必不可少的…

室内空气污染愈演愈烈,新风系统如何实现呼吸自由

室内空气污染到底有多可怕&#xff1f;有研究发现&#xff0c;室内空气污染比室外空气污染严重2~3倍&#xff0c;甚至几十倍&#xff0c;我国每年有11.1万人因室内空气污染死亡&#xff0c;全球更是高达430万人&#xff0c;68%的人体疾病与室内污染有关&#xff0c;90%的白血病…