MySQL唯一索引有重复值且不是bug的场景

Posted bisal(Chen Liu)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL唯一索引有重复值且不是bug的场景相关的知识,希望对你有一定的参考价值。

围绕着关系型数据库唯一索引相关的问题,还是不少的,可参考历史文章,

MySQL唯一索引和NULL空值之间的关系

Oracle唯一索引和NULL空值之间的关系

MySQL和Oracle在索引名称唯一性方面的不同设计

主键和唯一约束的索引肯定唯一?

碰巧看到GreatSQL社群推送的这篇文章《故障案例:MySQL唯一索引有重复值,官方却说This is not a bug》,给我们介绍了mysql数据库中唯一索引和重复值相关的一个场景,值得学习借鉴。

一、问题

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

二、原因

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

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

三、故障解决方案

(1)临时解决方案

恢复主从:

    • 在从节点开启会话

    • set sql_log_bin=0

    • 删除表的唯一索引

    • 重新启动复制线程

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

(2)永久解决方案

  1. 业务自己去重,不要插入重复数据。

  2. 参数unique_checks保持为1。

  3. 关于重复的业务数据:与业务交流,确定重复数据的处理方式。

    四、复现步骤

1. 表结构,

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

2. 查询数据,

3. 拼接SQL

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

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)

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

近期更新的文章:

数字中国建设整体布局规划

MySQL日志 - Error Log错误日志

MySQL日志 - General Query Log

最近碰到的一些问题

基金词汇的普及 - QDII和QFII (RQFII)

近期的热文:

推荐一篇Oracle RAC Cache Fusion的经典论文

"红警"游戏开源代码带给我们的震撼

文章分类和索引:

公众号1100篇文章分类和索引

以上是关于MySQL唯一索引有重复值且不是bug的场景的主要内容,如果未能解决你的问题,请参考以下文章

MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引

Mysql 系列 | 索引(唯一索引 or 普通索引)

mysql “索引”能重复吗?“唯一索引”与“索引”区别是啥?

mysql 添加数据判断是不是重复添加

Mysql实战篇之普通索引和唯一索引--01

MySQL45讲唯一索引和普通索引的选择