首页 > 数据库 >故障案例:MySQL唯一索引有重复值,官方却说This is not a bug

故障案例:MySQL唯一索引有重复值,官方却说This is not a bug

时间:2023-02-17 13:45:06浏览次数:54  
标签:MySQL GreatSQL bug 索引 pad mysql id

  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者:飞鱼过天
  • 文章来源:GreatSQL社区原创

  • 问题
  • 原因
  • 故障解决方案
  • 复现步骤
  • 参考文献

一、问题:

MySQL5.7.38主从架构,主节点唯一索引上(唯一索引不是主键)有重复值,全部从节点报1062,SQL线程状态异常,根据SQL线程报的binlog位置点,insert 数据时有重复值,插入失败

二、原因:

unique_checks=0时导致,在bug(106121)列表中官方解释的原因:该参数关闭,维护唯一索引时,不会进行物理读,只会进行内存读,来确保唯一索引的唯一性,即如果内存中有冲突数据就报1062,如果内存中没有冲突数据插入成功,不会进行io来将唯一索引相关的数据页拉取到内存。

官方的回复“IMHO this is not a bug”,我理解的意思“不要你觉得,我要我觉得,我就是这么玩的”。

三、故障解决方案:

一、临时解决方案

  • 恢复主从:
    • 在从节点开启会话
    • set sql_log_bin=0
    • 删除表的唯一索引
    • 重新启动复制线程

缺点是:不能够解决数据重复的问题,切换主从后会面临更多重复数据的问题,如果从节点接收查请求且使用到了原唯一索引的字段,那sql效率会严重下降,但是可以解决主从复制停止的问题

二、永久解决方案

  1. 业务自己去重,不要插入重复数据
  2. 参数unique_checks保持为1
  3. 关于重复的业务数据:与业务交流,确定重复数据的处理方式

四、复现步骤:

1. 表结构:

mysql> create database wl;
mysql> show create table wl.lgf\G
*************************** 1. row ***************************
       Table: lgf
Create Table: CREATE TABLE `lgf` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `c` (`c`,`pad`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8

Python生成随机数据,插入表,并另起会话观察总数据量约10w条左右(保证聚簇索引中的前边的数据与后边的数据所在的叶子节点的页相差很远):

rand.py
import random
import os
while True:
    i=str(random.randint(1000,8000000))
    a=str(random.randint(1000000000000000,8000000000000000))
    b=str(random.randint(1000000000000000,8000000000000000))
    c=str(random.randint(100000,800000))
    sql="insert ignore into lgf(id,k,c,pad) values(%s,%s,%s,%s) " % (i,c,a,b)
    os.system('mysql -uroot -p123456 -h127.0.0.1 -P3306 -e "use wl;%s"' % (sql))

2. 查询数据:

查询前10条数据:
mysql> select * from wl.lgf order by id limit 10;
+------+--------+------------------+------------------+
| id   | k      | c                | pad              |
+------+--------+------------------+------------------+
| 1058 | 162327 | 1693367460515515 | 4503256156555111 |
| 1072 | 581438 | 7079984640802065 | 3180334749170868 |
| 1139 | 160022 | 5072986485096872 | 4163430310554381 |
| 1193 | 780611 | 4790797228737408 | 2940698105313885 |
| 1234 | 395757 | 4904177529354516 | 4353197763651083 |
| 1243 | 725513 | 5525166443023382 | 5731401212245669 |
| 1262 | 749163 | 1132694876665847 | 5159069792931202 |
| 1280 | 415220 | 2770815803363126 | 3979264947141008 |
| 1316 | 329253 | 6088415865037450 | 6035685143204331 |
| 1360 | 403078 | 3344825394389018 | 7962994492618902 |
+------+--------+------------------+------------------+
10 rows in set (0.00 sec)
id=1360 c=3344825394389018 pad=7962994492618902

3. 拼接SQL

c与pad的值与id=1360值相等,id=1000000000(表中无该id行)

insert into wl.lgf(id,c,pad) values(10000000,'3344825394389018','7962994492618902') ;

4. 重启mysqld

目的是清除缓存 为了清空MySQL缓存容,还可结合以下几个参数 修改my.cnf文件,重启MySQL实例

  • innodb_buffer_pool_load_at_startup = 0
  • innodb_buffer_pool_dump_at_shutdown = 0

5. 重新插入重复唯一索引数据:

mysql> set unique_checks=0;

mysql> use wl

mysql> insert into wl.lgf(id,c,pad) values(10000000,'3344825394389018','7962994492618902') ;
Query OK, 1 row affected (0.00 sec)

6. 查询:force index指定主键查询数据

mysql> select * from wl.lgf force index(primary) where c='3344825394389018' and pad='7962994492618902';
+----------+--------+------------------+------------------+
| id       | k      | c                | pad              |
+----------+--------+------------------+------------------+
|     1360 | 403078 | 3344825394389018 | 7962994492618902 |
| 10000000 |      0 | 3344825394389018 | 7962994492618902 |
+----------+--------+------------------+------------------+
2 rows in set (0.37 sec)

参考文档

MySQL Bugs: #106121: Unique key constraint invalid(https://bugs.mysql.com/bug.php?id=106121)
MySQL :: MySQL 8.0 Reference Manual :: 5.1.8 Server System Variables(https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_unique_checks)


Enjoy GreatSQL

标签:MySQL,GreatSQL,bug,索引,pad,mysql,id
From: https://www.cnblogs.com/greatsql/p/17129847.html

相关文章

  • 【MySQL-视图/存储过程/存储函数/触发器】
    零、本文纲要一、视图二、存储过程三、存储函数四、触发器tips:Ctrl+F快速定位到所需内容阅读吧。一、视图0、表&数据准备--新建表格createtabletb_test(idint......
  • 【MySQL-SQL优化:主键,order by,group by,limit,count,update】
    零、本文纲要一、插入数据二、主键优化三、orderby优化四、groupby优化五、limit优化六、count优化七、update优化update优化tips:Ctrl+F快速定位到所需内容阅读吧。一、......
  • 项目没发版却出现了bug,原来是chrome春节前下毒
    项目背景这个功能是属于一个基础功能,通过npm私有仓库维护版本这个基础功能呢,很多项目中都在使用。如果基础功能发了新版本,业务部门不进行升级安装,那么这个业务线的项......
  • MySQL数据库的几种登录方式
    1234567891011前提:连接进入mysql数据库本机安装的myslq基础信息:host="localhost",数据库主机地址:127.0.0.1port=3306,端口号user="root",myslql数据库......
  • mysql 两表,两个update_time排序问题
    当有2表要联表查询时,各有1个update_time。大于某个时间开始查询,查询更新的数据,根据update_time排序(两张表有可能之更新一张表而已)。 1.工单表CREATETABLE`shop_work......
  • 银河麒麟系统安装mysql数据库
    1.1 准备材料mysql-5.7.28-linux-glibc2.12-x86_64.tar.gzMySQL5.7下载地址https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz......
  • Mysql中的--single-transaction会锁表吗
    当时用mysqldump配置主从的时候,要设置--single-transaction,这个参数将保证备份的数据库处于一致的状态一般的备份语句如下:mysqldump-uroot-S/data/3306/data/mysql.sock......
  • mysql B+ 树与 Buffer Pool
    转自 https://lvwenhan.com/tech-epic/506.html内存缓存BufferPoolBufferPool是在MySQL启动的时候,向操作系统申请的一片连续的内存空间,默认为128MB,强烈建议任何......
  • MYSQL占用内存过高问题的解决结果记录
    问题:发现docker容器mysql的内存使用高,达到9个G快满了。开始按网上资料,查了以下二个方面,结果不是这二方面的问题,这里不再详述:1)连接池占用内存情况2)会话占用内存情况最......
  • 利用sshfs快速重做mysql主从
    先清空slavedata目录master:mkdir/tmp/data;sshfs-p22-oallow_other,[email protected]:/home/mysql5.7.39/data/tmp/data/;xtrabackup–defaults-file=/ho......